ufw 防火墙常用命令,省的每次都问 Gemini
sudo apt update && sudo apt install -y ufw
sudo ufw allow 22022/tcp sudo ufw allow 2443/udp
sudo ufw default deny incoming sudo ufw default allow outgoing
sudo ufw enable sudo ufw status verbose
sudo apt update && sudo apt install -y ufw
sudo ufw allow 22022/tcp sudo ufw allow 2443/udp
sudo ufw default deny incoming sudo ufw default allow outgoing
sudo ufw enable sudo ufw status verbose
iOS:设置->电话->来电阻止与身份识别->实时主叫号码查询
来电时系统通过 Live Caller ID Lookup 用 PIR 查询服务端,把号码身份显示在系统来电界面
利用AI生成DEMO可以跑通,但如果实际应用存在几个问题:
比 Call Directory Extension 插件的好处是不用把庞大的号码库下载到手机上。
本来想用 wordpress 来建站,但是可能AI “太笨了”,制作的主题样式和后台功能总是不满足需求,也可能是 AI对 Wordpress 功能了解不足吧。
然后让 AI 根据设计的前端页面,基于 python3 + ant design 来开发后台,除了权限体系外还有具体的功能:
文章管理、分类管理、标签管理、商城管理(应用商城)、评论管理、广告管理、友链管理、爬虫管理、投诉管理、模型管理、安全记录。
其中文章管理,增加AI写作助手,可根据网址抓取+自动填充文章内容,大模型管理可配置各类API格式模型用于总结网址内容。
爬虫自动分析目标网页结构,分析文章内容自动填充内容并送审。
精选收录全球优质、前沿的人工智能软件,涵盖实用 AI 写作、AI 绘画、编程、音视频及办公等各领域应用
AILOL.xyz(爱乐AI)是一个专业精选的 AI 工具、人工智能应用与 AI 导航分类目录网站。精选收录全球优秀的前沿人工智能软件,助您极速发现实用 AI 利器!
基于 Python FastAPI + SQLite + Ant Design + ZLMediaKit + Jessibuca 实现的简易 ONVIF / RTSP 摄像头监控平台。
https://github.com/budwk/budcam 源码及安装包地址
制作一款 wordpress 6.9 版本下的反垃圾评论插件,插件名称 wizspam,支持根据关键词过滤、IP地址过滤,支持对关键词、IP的管理等功能。
一款功能强大的 WordPress 反垃圾评论插件,支持基于关键词和 IP 地址的智能过滤。
192.168.1.100192.168.1.*192.168.1.0/24PS:有需要的可以评论留下 Email,我会免费发送给你~~
Ondřej Surý 的 PPA 是 Debian/Ubuntu 生态中最权威的 PHP 源,它会第一时间同步 PHP 8.5.x 的稳定版。
<code>sudo apt update
sudo apt install -y software-properties-common
# 添加 PPA 源(如果已添加则会自动跳过)
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
为了确保你的业务能正常运行,除了安装核心包,还需要安装常用的扩展(以替代 8.0 版本的扩展):
<code># 安装 PHP 8.5 核心、FPM 及常用扩展
sudo apt install -y php8.5 php8.5-cli php8.5-fpm php8.5-common php8.5-mysql \
php8.5-xml php8.5-curl php8.5-mbstring php8.5-zip php8.5-gd php8.5-intl
安装后,系统内会并存多个 PHP 版本。你需要将命令行默认指向 8.5:
<code># 切换 CLI 版本
sudo update-alternatives --set php /usr/bin/php8.5
# 验证版本
php -v
如果你使用的是 Nginx,需要手动修改站点配置文件(通常在 /etc/nginx/sites-enabled/):
fastcgi_pass 这一行。fastcgi_pass unix:/run/php/php8.0-fpm.sock;fastcgi_pass unix:/run/php/php8.5-fpm.sock;sudo nginx -t && sudo systemctl restart nginx确认网站运行无误后,可以删除 PHP 8.0 以节省 磁盘空间:
<code>sudo apt purge php8.0*
sudo apt autoremove -y
背景:2013年比特币兴起的时候,注册了比特币官网账号及钱包,从TB等处买了少量BTC,大概有0.02个吧,当时助记词存在硬盘上,N年来电脑换了好几个,最终由于Thinkpad X1 SSD硬盘挂了(见文章:https://wizzer.cn/archives/3552),导致历史备份文件永久丢失。最近从邮箱中找到了当时钱包的备份文件,wallet.aes.json 但密钥文件使用密码加密了,尝试了一堆常用密码,都不对(不知道当时脑子咋想了,弄那么复杂的密码干啥),于是尝试破解密码。
这个工具主要通过海量的密码词典,进行匹配,看是否有可能匹配的密码组合:
python btcrecover.py --wallet wallet.aes.json --passwordlist weakpass.txt --no-dupchecks
–no-dupchecks 关闭重复猜测检查以节省内存
import itertools
import random
def generate_passwords(base_string, max_length=5):
# 生成所有可能的字符组合,允许任意顺序
base_list = list(base_string)
for length in range(1, max_length + 1):
for combo in itertools.product(base_list, repeat=length):
# 生成大小写的所有组合
for case in itertools.product(*[(char.lower(), char.upper()) for char in combo]):
yield ''.join(case)
def save_to_file(passwords, filename):
with open(filename, 'w') as file:
for password in passwords:
file.write(password + '\n')
if __name__ == "__main__":
base_string = 'abcdefg123456'
max_length = 11 # 可以根据需要调整
passwords = generate_passwords(base_string, max_length)
save_to_file(passwords, 'passwords.txt')
print(f"生成的密码已保存到 passwords.txt")
然而,使用了weakpass网站的上十亿密码组合,依旧没有匹配到我的密码……
尝试用生成密码的方式找回密码中……
mkdir tmp
cd tmp
# 解压jar主包
jar xf ../main.jar
# 编译lib文件夹下某子jar依赖包, 生成class文件,使用classpath加载依赖包
javac -cp "../*:." com/budwk/Demo.java
# 将class文件打包到jar包中
jar uf demo.jar com/budwk/Demo.class
# 手动覆盖新的 demo.jar 包
# 不能使用这个更新命令,会导致jar包被二次压缩
# jar uf ../main.jar lib/demo.jar
# 使用0这个参数,将解压文件打包到jar包中
jar cfM0 ../main.jar *
@Column
@ColDefine(customType = "GEOGRAPHY(Point,4326)", adaptor = PsqlPointAdaptor.class)
@ApiModelProperty(description = "坐标")
private String geomPoint;//值格式为"POINT(经度 纬度)"
import net.postgis.jdbc.PGgeometry;
import net.postgis.jdbc.geometry.Point;
import org.nutz.dao.jdbc.ValueAdaptor;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
public class PsqlPointAdaptor implements ValueAdaptor {
@Override
public Object get(ResultSet rs, String colName) throws SQLException {
return rs.getObject(colName);
}
@Override
public void set(PreparedStatement stat, Object obj, int index) throws SQLException{
if (null == obj) {
stat.setNull(index, Types.NULL);
} else {
String pointStr = (String) obj;
Point point = new Point(pointStr);
PGgeometry pgGeometry = new PGgeometry(point);
stat.setObject(index, pgGeometry, Types.OTHER);
}
}
}
<properties>
<postgis-jdbc.version>2024.1.0</postgis-jdbc.version>
</properties>
<dependencies>
<!-- PostGIS扩展类型 -->
<dependency>
<groupId>net.postgis</groupId>
<artifactId>postgis-jdbc</artifactId>
<version>${postgis-jdbc.version}</version>
</dependency>
Let`s Encrypt 证书自动获取和部署
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx
sudo systemctl reload nginx
sudo certbot renew --dry-run
1、ArgGIS 按图层分别导出shp
原始没有坐标系,要手动配准:
投影坐标 4524 CGCS2000_3_Degree_GK_Zone_36

2、GeoServer
1)创建工作区
2)数据存储-添加新的数据存储-选择文件夹 Directory of spatial files (shapefiles)
3)图层-添加新的资源-选择要发布的文件-Native Bounding Box 从数据中计算
问题1:只能收到APP在线时推送的消息,离线消息收不到
问题2:一台设备一天只能收到2次消息推送
解决方法:
1、uniapp 要正确获取clientId,并且APP要获取通知权限
bindPushCid() {
var timer = setTimeout(function() {
plus.push.getClientInfoAsync(function(info) {
if (info.clientid) {
// 绑定到后台用户
updateGetuiClientId(info.clientid);
clearInterval(timer);
}
}, function(e) {
console.log(JSON.stringify(e));
})
}, 1000)
},
permissionPush(){
let platform = uni.getSystemInfoSync().platform
if (platform == 'android') {
/* 获取当前手机是否有通知权限 */
// let main = plus.android.runtimeMainActivity();
// let pkName = main.getPackageName();
// console.log("是否有通知权限pkName",pkName);
// let NotificationManagerCompat = plus.android.importClass("android.support.v4.app.NotificationManagerCompat");
// console.log("是否有通知权限NotificationManagerCompat",NotificationManagerCompat);
// let packageNames = NotificationManagerCompat.from(main);
var main = plus.android.runtimeMainActivity();
var NotificationManagerCompat = plus.android.importClass("androidx.core.app.NotificationManagerCompat");
let packageNames = NotificationManagerCompat.from(main);
let pkName = main.getPackageName();
if (!packageNames.areNotificationsEnabled()) { //手机没有开启通知的权限
uni.showModal({
title: '通知权限',
content: '通知权限暂未开启',
cancelText: '暂不开启',
confirmText: '前往开启',
success: function (res) {
if (res.confirm) {
let uid = main.getApplicationInfo().plusGetAttribute("uid");
let Intent = plus.android.importClass('android.content.Intent');
let Build = plus.android.importClass("android.os.Build");
let intent = '';
//android 8.0引导
if (Build.VERSION.SDK_INT >= 26) {
intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
intent.putExtra('android.provider.extra.APP_PACKAGE', pkName);
} else if (Build.VERSION.SDK_INT >= 21) { //android 5.0-7.0
intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
intent.putExtra("app_package", pkName);
intent.putExtra("app_uid", uid);
} else { //(<21)其他--跳转到该应用管理的详情页
let Settings = plus.android.importClass("android.provider.Settings");
let Uri = plus.android.importClass("android.net.Uri");
intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
let uri = Uri.fromParts("package", main.getPackageName(), null);
intent.setData(uri);
}
// 跳转到该应用的系统通知设置页
main.startActivity(intent);
} else if (res.cancel) {
console.log('用户点击取消');
}
},
fail: () => {},
complete: () => {}
});
}
}
}
2、华为开发者后台,申请“自分类权益”,以便解除通知条数限制,现在申请很简单,提交示例和截图,系统直接审核通过

3、厂家参数要注意细节
因为importance和category参数,调试很久
Map<String, Map<String, Object>> options = new HashMap<>();
Map<String, Object> oop = new HashMap<>();
oop.put("/message/android/notification/badge/class", "io.dcloud.PandoraEntry");
oop.put("/message/android/notification/badge/add_num", 1);
oop.put("/message/android/notification/importance", "NORMAL");
oop.put("/message/android/category", "WORK");
options.put("HW", oop);
ups.setOptions(options);
4、服务端完整代码
package com.budwk.app;
import com.getui.push.v2.sdk.ApiHelper;
import com.getui.push.v2.sdk.GtApiConfiguration;
import com.getui.push.v2.sdk.api.PushApi;
import com.getui.push.v2.sdk.common.ApiResult;
import com.getui.push.v2.sdk.dto.CommonEnum;
import com.getui.push.v2.sdk.dto.req.Audience;
import com.getui.push.v2.sdk.dto.req.AudienceDTO;
import com.getui.push.v2.sdk.dto.req.message.PushChannel;
import com.getui.push.v2.sdk.dto.req.message.PushDTO;
import com.getui.push.v2.sdk.dto.req.message.PushMessage;
import com.getui.push.v2.sdk.dto.req.message.android.AndroidDTO;
import com.getui.push.v2.sdk.dto.req.message.android.GTNotification;
import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification;
import com.getui.push.v2.sdk.dto.req.message.android.Ups;
import com.getui.push.v2.sdk.dto.req.message.harmony.HarmonyDTO;
import com.getui.push.v2.sdk.dto.req.message.harmony.HarmonyNotification;
import com.getui.push.v2.sdk.dto.res.TaskIdDTO;
import com.gexin.rp.sdk.base.IPushResult;
import com.gexin.rp.sdk.base.impl.AppMessage;
import com.gexin.rp.sdk.base.impl.ListMessage;
import com.gexin.rp.sdk.base.impl.SingleMessage;
import com.gexin.rp.sdk.base.impl.Target;
import com.gexin.rp.sdk.exceptions.RequestException;
import com.gexin.rp.sdk.http.IGtPush;
import com.gexin.rp.sdk.template.*;
import com.gexin.rp.sdk.template.style.Style0;
import lombok.extern.slf4j.Slf4j;
import org.nutz.json.Json;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
public class GeTuiUtil {
private static String appId;
private static String appKey;
private static String masterSecret;
private static String host;
private static Long OfflineExpireTime;
private static String logo;
private static boolean isRing;
private static boolean isVibrate;
private static boolean isClearable;
private static int transmissionType;
private static PushApi pushApi;
// 初始化个推的系统app参数
static {
appId = "";
appKey = "";
masterSecret = "";
host = "http://sdk.open.api.igexin.com/apiex.htm";
OfflineExpireTime = 259200000L;
logo = "icon.png";
isRing = true;
isVibrate = true;
isClearable =true;
transmissionType = 1;
System.setProperty("http.maxConnections", "200");
GtApiConfiguration apiConfiguration = new GtApiConfiguration();
//填写应用配置
apiConfiguration.setAppId(appId);
apiConfiguration.setAppKey(appKey);
apiConfiguration.setMasterSecret(masterSecret);
// 接口调用前缀,请查看文档: 接口调用规范 -> 接口前缀
apiConfiguration.setDomain("https://restapi.getui.com/v2/");
// 实例化ApiHelper对象,用于创建接口对象
ApiHelper apiHelper = ApiHelper.build(apiConfiguration);
// 创建对象,建议复用。目前有PushApi、StatisticApi、UserApi
pushApi = apiHelper.creatApi(PushApi.class);
}
public static Map<String, Object> sendSingleNew(String title, String content, String cid) {
PushDTO<Audience> pushDTO = new PushDTO<Audience>();
pushDTO.setRequestId(System.currentTimeMillis() + "");
buildPushMessage(title, content, pushDTO);
Audience audience = new Audience();
pushDTO.setAudience(audience);
audience.addCid(cid);
ApiResult<Map<String, Map<String, String>>> apiResult = pushApi.pushToSingleByCid(pushDTO);
log.info("sendSingleNew result :" + Json.toJson(apiResult));
Map<String, Object> result = new HashMap<>();
result.put("code", apiResult.getCode());
if (apiResult.isSuccess()) {
result.put("data", apiResult.getData());
} else {
result.put("msg", apiResult.getMsg());
}
return result;
}
public static void main(String[] args) {
String title = "你有新的待办任务";
String content = "任务内容:测" + System.currentTimeMillis();
String cid = "77336b3d6d136da0cf56e288a7462949";
Map<String, Object> stringObjectMap = sendSingleNew(title, content, cid);
// List<String> cids = new ArrayList<>();
// cids.add(cid);
// Map<String, Object> stringObjectMap = sendBatchNew(title, content, cids);
// Map<String, Object> stringObjectMap = sendAllClientNew(title, content);
//
}
private static PushMessage buildPushMessage(String title, String content, PushDTO pushDTO) {
PushMessage pushMessage = new PushMessage();
pushDTO.setPushMessage(pushMessage);
GTNotification notification = new GTNotification();
pushMessage.setNotification(notification);
notification.setTitle(title);
notification.setBody(content);
notification.setBadgeAddNum("1");
notification.setClickType(CommonEnum.ClickTypeEnum.TYPE_STARTAPP.type);
notification.setSlotType("2");
notification.setCategory("CATEGORY_REMINDER");
PushChannel pushChannel = new PushChannel();
pushDTO.setPushChannel(pushChannel);
AndroidDTO androidDTO = new AndroidDTO();
pushChannel.setAndroid(androidDTO);
Ups ups = new Ups();
androidDTO.setUps(ups);
ThirdNotification thirdNotification = new ThirdNotification();
ups.setNotification(thirdNotification);
thirdNotification.setTitle(title);
thirdNotification.setBody(content);
thirdNotification.setClickType(CommonEnum.ClickTypeEnum.TYPE_STARTAPP.type);
Map<String, Map<String, Object>> options = new HashMap<>();
Map<String, Object> oop = new HashMap<>();
oop.put("/message/android/notification/badge/class", "io.dcloud.PandoraEntry");
oop.put("/message/android/notification/badge/add_num", 1);
oop.put("/message/android/notification/importance", "NORMAL");
oop.put("/message/android/category", "WORK");
options.put("HW", oop);
ups.setOptions(options);
HarmonyDTO harmonyDTO = new HarmonyDTO();
pushChannel.setHarmony(harmonyDTO);
HarmonyNotification harmonyNotification = new HarmonyNotification();
harmonyDTO.setNotification(harmonyNotification);
harmonyNotification.setTitle(title);
harmonyNotification.setBody(content);
harmonyNotification.setCategory("CATEGORY_REMINDER");
harmonyNotification.setClickType(CommonEnum.ClickTypeEnum.TYPE_STARTAPP.type);
return pushMessage;
}
private static Map<String, Object> send(AbstractTemplate template, List<String> cids) {
if (cids == null || cids.size() == 0) {
// 给appId下所有人发
return sendAllClient(template);
}
if (cids.size() == 1) {
// 单发
Map<String, Object> result = sendSingle(template, cids.get(0));
return result;
} else {
// 群发
Map<String, Object> result = sendBatch(template, cids);
return result;
}
}
private static Map<String, Object> sendNew(String title, String content, List<String> cids) {
log.info("进入推送信息:" + title);
if (cids == null || cids.size() == 0) {
// 给appId下所有人发
Map<String, Object> stringObjectMap = sendAllClientNew(title, content);
log.info("APP群推发送返回结果:" + Json.toJson(stringObjectMap));
return stringObjectMap;
}
if (cids.size() == 1) {
// 单发
Map<String, Object> result = sendSingleNew(title, content, cids.get(0));
log.info("单推发送返回结果:" + Json.toJson(result));
return result;
} else {
// 群发
Map<String, Object> result = sendBatchNew(title, content, cids);
log.info("群推发送返回结果:" + Json.toJson(result));
return result;
}
}
/**
* @Description 发送通知模板消息
* @Author daitao
* @version 1.0
* @Date 2019/4/24 17:57
* @Param title:消息标题
* @Param content:消息内容
* @Param cids: 1、null或size==0:表示给appId下所有人发
* 2、size为1:单发
* 3、size大于1:群发
* @Return map类型, 可能为null,例如:"{result=ok, contentId=OSL-0424_y2LxEeM6hvA0yhTqa77qw4,
* details={"c85fa1218fe4c54652a77bef22726fb0":"TokenMD5Error",
* "a5800ff27659a5258b8ba86e4e1d7c87":"successed_online"
* }
* }"
* result==ok,发送成功,details里面是每个cid对应的发送结果,包含successed表示成功,其他失败
*/
public static Map<String, Object> sendNotification(String title, String content, List<String> cids) {
NotificationTemplate template = buildNotificationTemplate(title, content);
return send(template, cids);
}
public static Map<String, Object> sendNotificationNew(String title, String content, List<String> cids) {
return sendNew(title, content, cids);
}
/**
* @param
* @param template
* @param msgItem
* @return
* @throws
* @author daitao
* @version 1.0
* @description 个推单发
* @date 2019/4/12
**/
private static Map<String, Object> sendSingle(AbstractTemplate template, String cid) {
IGtPush push = new IGtPush(host, appKey, masterSecret);
SingleMessage message = new SingleMessage();
message.setOffline(true);
// 离线有效时间,单位为毫秒,可选
message.setOfflineExpireTime(OfflineExpireTime);
message.setData(template);
// 可选,1为wifi,0为不限制网络环境。根据手机处于的网络情况,决定是否下发
message.setPushNetWorkType(0);
Target target = new Target();
target.setAppId(appId);
target.setClientId(cid);
IPushResult ret;
try {
ret = push.pushMessageToSingle(message, target);
} catch (RequestException e) {
e.printStackTrace();
ret = push.pushMessageToSingle(message, target, e.getRequestId());
}
return ret.getResponse();
}
/**
* @param
* @param template
* @param msgItem
* @return
* @throws
* @author daitao
* @version 1.0
* @description 个推单发
* @date 2019/4/12
**/
private static Map<String, Object> sendBatch(AbstractTemplate template, List<String> cids) {
// 配置返回每个用户返回用户状态,可选
System.setProperty("gexin_pushList_needDetails", "true");
IGtPush push = new IGtPush(host, appKey, masterSecret);
// 通知透传模板
ListMessage message = new ListMessage();
message.setData(template);
// 设置消息离线,并设置离线时间
message.setOffline(true);
// 离线有效时间,单位为毫秒,可选
message.setOfflineExpireTime(OfflineExpireTime);
// taskId用于在推送时去查找对应的message
String taskId = push.getContentId(message);
List<Target> targets = handleTargets(cids);
IPushResult ret = push.pushMessageToList(taskId, targets);
return ret.getResponse();
}
private static Map<String, Object> sendBatchNew(String title, String content, List<String> cids) {
Map<String, Object> result = new HashMap<>();
PushDTO<String> pushDTO = new PushDTO<String>();
pushDTO.setRequestId(System.currentTimeMillis() + "");
buildPushMessage(title, content, pushDTO);
ApiResult<TaskIdDTO> createResult = pushApi.createMsg(pushDTO);
log.info("sendBatchNew createResult :" + Json.toJson(createResult));
result.put("code", createResult.getCode());
if (createResult.isSuccess()) {
result.put("data", createResult.getData());
TaskIdDTO taskIdDTO = createResult.getData();
AudienceDTO pushBatchDTO = new AudienceDTO();
pushBatchDTO.setTaskid(taskIdDTO.getTaskId());
Audience audience = new Audience();
audience.setCid(cids);
pushBatchDTO.setAudience(audience);
ApiResult<Map<String, Map<String, String>>> apiResult = pushApi.pushListByCid(pushBatchDTO);
log.info("sendBatchNew apiResult :" + Json.toJson(apiResult));
result.put("code", apiResult.getCode());
if (apiResult.isSuccess()) {
result.put("data", apiResult.getData());
} else {
result.put("msg", apiResult.getMsg());
}
} else {
result.put("msg", createResult.getMsg());
}
return result;
}
private static List<Target> handleTargets(List<String> cids) {
List<Target> targets = new ArrayList<>();
for (String cid : cids) {
Target target = new Target();
target.setAppId(appId);
target.setClientId(cid);
targets.add(target);
}
return targets;
}
private static NotificationTemplate buildNotificationTemplate(String title, String content) {
NotificationTemplate template = new NotificationTemplate();
// 设置APPID与APPKEY
template.setAppId(appId);
template.setAppkey(appKey);
template.setTransmissionType(transmissionType);
Style0 style = new Style0();
// 设置通知栏标题与内容
style.setTitle(title);
style.setText(content);
// 配置通知栏图标
style.setLogo(logo);
// 配置通知栏网络图标
style.setLogoUrl("");
// 设置通知是否响铃,震动,或者可清除
style.setRing(isRing);
style.setVibrate(isVibrate);
style.setClearable(isClearable);
template.setStyle(style);
return template;
}
/**
* @Description
* @Author daitao
* @version 1.0
* @Date 2019/4/24 17:57
* @Param cids: 1、null或size==0:表示给appId下所有人发
* 2、size为1:单发
* 3、size大于1:群发
* @Return
* @Exception
*/
public static Map<String, Object> sendLinkTemplate(String title, String content, String openUrl, List<String> cids) {
LinkTemplate template = buildLinkTemplate(title, content, openUrl);
return send(template, cids);
}
private static LinkTemplate buildLinkTemplate(String title, String content, String openUrl) {
LinkTemplate template = new LinkTemplate();
// 设置APPID与APPKEY
template.setAppId(appId);
template.setAppkey(appKey);
Style0 style = new Style0();
// 设置通知栏标题与内容
style.setTitle(title);
style.setText(content);
// 配置通知栏图标
style.setLogo(logo);
// 配置通知栏网络图标
style.setLogoUrl("");
// 设置通知是否响铃,震动,或者可清除
style.setRing(isRing);
style.setVibrate(isVibrate);
style.setClearable(isClearable);
template.setStyle(style);
// 设置打开的网址地址
template.setUrl(openUrl);
return template;
}
/**
* @Description
* @Author daitao
* @version 1.0
* @Date 2019/4/24 17:57
* @Param cids: 1、null:表示给appId下所有人发
* 2、size为1:单发
* 3、size大于1:群发
* @Return
* @Exception
*/
public static Map<String, Object> sendNotyPopLoadTemplate(String title, String content,
String popTitle, String popContent, String downloadTitle, String downloadIcon, String downloadUrl, List<String> cids) {
NotyPopLoadTemplate template = buildNotyPopLoadTemplate(title, content, popTitle, popContent, downloadTitle, downloadIcon, downloadUrl);
return send(template, cids);
}
/**
* @param title 消息标题
* @param content 消息内容
* @param popTitle 弹框标题
* @param popContent 弹框内容
* @param downloadTitle 下载标题
* @param downloadIcon 下载图标
* @param downloadUrl 下载的url资源地址
* @return
*/
private static NotyPopLoadTemplate buildNotyPopLoadTemplate(String title, String content,
String popTitle, String popContent, String downloadTitle, String downloadIcon, String downloadUrl
) {
NotyPopLoadTemplate template = new NotyPopLoadTemplate();
// 设置APPID与APPKEY
template.setAppId(appId);
template.setAppkey(appKey);
Style0 style = new Style0();
// 设置通知栏标题与内容
style.setTitle(title);
style.setText(content);
// 配置通知栏图标
style.setLogo(logo);
// 配置通知栏网络图标
style.setLogoUrl("");
// 设置通知是否响铃,震动,或者可清除
style.setRing(isRing);
style.setVibrate(isVibrate);
style.setClearable(isClearable);
template.setStyle(style);
// 设置弹框标题与内容
template.setPopTitle(popTitle);
template.setPopContent(popContent);
// 设置弹框显示的图片
template.setPopImage("");
template.setPopButton1("下载");
template.setPopButton2("取消");
// 设置下载标题
template.setLoadTitle(downloadTitle);
template.setLoadIcon(downloadIcon);
//设置下载地址
template.setLoadUrl(downloadUrl);
return template;
}
/**
* @Description
* @Author daitao
* @version 1.0
* @Date 2019/4/24 17:57
* @Param cids: 1、null:表示给appId下所有人发
* 2、size为1:单发
* 3、size大于1:群发
* @Return
* @Exception
*/
public static Map<String, Object> sendTransmissionTemplate(String title, String content, List<String> cids) {
TransmissionTemplate template = buildTransmissionTemplate(title, content);
return send(template, cids);
}
/**
* 安卓推送透传消息模板
*
* @param title
* @param content
* @return
*/
private static TransmissionTemplate buildTransmissionTemplate(String title, String content) {
TransmissionTemplate template = new TransmissionTemplate();
template.setAppId(appId);
template.setAppkey(appKey);
// 透传消息设置,1为强制启动应用,客户端接收到消息后就会立即启动应用;2为等待应用启动
template.setTransmissionType(transmissionType);
template.setTransmissionContent(content);
return template;
}
/**
* @param oldTaskId 指定需要撤回消息对应的taskId
* @param force 客户端没有找到对应的taskid,是否把对应appid下所有的通知都撤回
* @Description
* @Author daitao
* @version 1.0
* @Date 2019/4/24 17:57
* @Param cids: 1、null:表示给appId下所有人发
* 2、size为1:单发
* 3、size大于1:群发
* @Return
* @Exception
*/
public static Map<String, Object> sendRevokeTemplate(String oldTaskId, boolean force, List<String> cids) {
RevokeTemplate template = getRevokeTemplate(oldTaskId, force);
return send(template, cids);
}
/**
* 获取撤回模板
*
* @param oldTaskId 指定需要撤回消息对应的taskId
* @param force 客户端没有找到对应的taskid,是否把对应appid下所有的通知都撤回
* @return
*/
private static RevokeTemplate getRevokeTemplate(String oldTaskId, boolean force) {
RevokeTemplate template = new RevokeTemplate();
template.setAppId(appId);// 应用appid
template.setAppkey(appKey);// 应用appkey
template.setOldTaskId(oldTaskId);
return template;
}
/**
* 发个应用的所有客户端
*
* @param template
* @return
*/
private static Map<String, Object> sendAllClient(AbstractTemplate template) {
IGtPush push = new IGtPush(host, appKey, masterSecret);
// 定义"点击链接打开通知模板",并设置标题、内容、链接
List<String> appIds = new ArrayList<String>();
appIds.add(appId);
// 定义"AppMessage"类型消息对象,设置消息内容模板、发送的目标App列表、是否支持离线发送、以及离线消息有效期(单位毫秒)
AppMessage message = new AppMessage();
message.setData(template);
message.setAppIdList(appIds);
message.setOffline(true);
message.setOfflineExpireTime(OfflineExpireTime);
IPushResult ret = push.pushMessageToApp(message);
return ret.getResponse();
}
private static Map<String, Object> sendAllClientNew(String title, String content) {
PushDTO<String> pushDTO = new PushDTO<String>();
pushDTO.setRequestId(System.currentTimeMillis() + "");
pushDTO.setAudience("all");
buildPushMessage(title, content, pushDTO);
ApiResult<TaskIdDTO> apiResult = pushApi.pushAll(pushDTO);
Map<String, Object> result = new HashMap<>();
log.info("sendAllClientNew result :" + Json.toJson(apiResult));
result.put("code", apiResult.getCode());
if (apiResult.isSuccess()) {
result.put("data", apiResult.getData());
} else {
result.put("msg", apiResult.getMsg());
}
return result;
}
}
pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!--个推-->
<dependency>
<groupId>com.gexin.platform</groupId>
<artifactId>gexin-rp-sdk-http</artifactId>
<version>4.1.0.1</version>
</dependency>
<dependency>
<groupId>com.gexin.platform</groupId>
<artifactId>gexin-rp-sdk-base</artifactId>
<version>4.0.0.26</version>
</dependency>
<dependency>
<groupId>com.gexin.platform</groupId>
<artifactId>gexin-rp-sdk-template</artifactId>
<version>4.0.0.20</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.gexin.platform/gexin-rp-fastjson -->
<!-- https://mvnrepository.com/artifact/com.getui.push/restful-sdk -->
<dependency>
<groupId>com.getui.push</groupId>
<artifactId>restful-sdk</artifactId>
<version>1.0.6.0</version>
</dependency>
<dependency>
<groupId>com.gexin.platform</groupId>
<artifactId>gexin-rp-fastjson</artifactId>
<version>1.0.0.1</version>
</dependency>
仓库
<repository>
<id>getui</id>
<url>http://mvn.gt.getui.com/nexus/content/repositories/releases/</url>
</repository>
以下以Nutz代码为例:
Header header = Header.create();
header.addv("Content-Type", "application/json");
header.addv("AppCode", appcode);
Request request = Request.create(url, Request.METHOD.POST);
NutMap body = NutMap.NEW();
body.put("kssj", kssj);
body.put("jssj", jssj);
request.setHeader(header);
request.setData(Json.toJson(body));
Sender sender = Sender.create(request).setTimeout(30 * 1000);
if (url.startsWith("https")) {
try {
SSLContext sslcontext = this.createIgnoreVerifySSL();
sender.setSSLSocketFactory(sslcontext.getSocketFactory());
sender.setHostnameVerifier((urlHostName, session) -> true);
} catch (Exception e) {
e.printStackTrace();
}
}
Response response = sender.send();
if (response.isOK()) {
//todo
}
private static class TrustAllManager
implements X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkServerTrusted(X509Certificate[] certs,
String authType) {
}
public void checkClientTrusted(X509Certificate[] certs,
String authType) {
}
}
public SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new CityLifelineServer.TrustAllManager()}, null);
return sc;
}
ALTER USER 'root'@'%' IDENTIFIED BY 'pwd' PASSWORD EXPIRE NEVER;
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd';
FLUSH PRIVILEGES;
BUDIOT 是一个开源的、企业级的物联网平台,它集成了设备管理、协议解析、消息订阅、场景联动等一系列物联网核心能力,支持以平台适配设备的方式连接海量设备,支持在线下发指令实现远程控制,支持扩展水电气等各类计费业务场景。
本平台是在千万级设备实时计费物联网平台经验基础上,在不损失性能的前提下进行功能删减、结构优化而来,小而美,同时又具备灵活的扩展性。
在线演示地址: https://demo.budiot.com 用户名: superadmin 密码: 1
基于自研 Java 微服务框架 https://budwk.com
budiot-access/budiot-access-gateway 设备网关,用于设备协议和 network 组件budiot-access/budiot-access-processor 设备数据上报业务处理模块budiot-server WEB 服务 API ,定时任务等budiot-access/budiot-access-network 网络组件,支持 TCP/MQTT/UDP/HTTP 等budiot-access/budiot-access-protocol 设备协议开发包,内含 demo 示例budiot-access/budiot-access-storage 设备数据存储,可扩展时序数据库等budiot-vue-admin Vue3 + Element-Plus默认采用 MongoDB 7 的时序集合,可根据项目规模需要,扩展为 TDEngine 等时序数据库
java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Comparison method violates its general contract!
错误代码:
children.sort((o1, o2) -> (int) (o2.getLong("createdAt", 0) - o1.getLong("createdAt", 0)));
修复后:
children.sort((o1, o2) -> Long.compare(o2.getLong("createdAt", 0), o1.getLong("createdAt", 0)));
排序器 children.sort((o1, o2) -> (int) (o2.getLong("createdAt", 0) - o1.getLong("createdAt", 0))); 存在一个潜在的问题,即当时间戳的差值超出 int 的范围时,强制转换为 int 会导致数据溢出,从而导致比较结果不正确。
一个解决方法是使用 Long.compare 方法进行比较,而不是手动进行减法运算。Long.compare 方法确保了比较的对称性和一致性。
Mongod 的服务模型是每个网络连接由一个单独的线程来处理,每个线程配置了1MB 的栈空间,当网络连接数太多时,过多的线程会导致上下文切换开销变大,同时内存开销也会上涨。
&maxPoolSize=xx 在ConnectionURI上追加上去即可,否则默认每个客户端就是高处100来个,平白的浪费资源启动需指定配置文件(配置数据库用户和密码,用户不可为默认用户)
python3 odoo-bin -c debian/odoo.conf -i base -d odoo
配置文件
[options]
; This is the password that allows database operations:
; admin_passwd = admin
db_host = 127.0.0.1
db_port = 5432
db_user = odoo
db_password = 1234567890
addons_path = /data/odoo/addons
default_productivity_apps = True
需安装依赖
pip3 install -r requirements.txt