emis-app/common/lbs/XdLbsUniSdk.js
2025-06-29 12:50:22 +08:00

494 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
XdLbsUniSdk
*/
class XdLbsUniSdk {
VERSION="1.0.0"
MAX_SENT_RETRY_COUNT = 9;
LBS_UP_FREQ = 60 ;
WS_URL = 'wss://pushlbs.xdadan.com/ws';
custNo = null;
deviceNo =null;
msisdn = null;
deviceInfo = null;
batteryInfo = null;
maximumAge = 60000;
token = null;
AUTH_TOKEN=null;
WS_INIT = 0;
WS_OPEN = 1;
WS_CLOSING = 2;
WS_CLOSE = 3;
// 和服务端连接的socket对象
ws = null;
// WS 回调函数
onOpenCallback =[];
onCloseCallback=[];
onErrorCallback =[];
onMessageCallback=[];
lbsWatcherId = null;
registerCheckTimer = null;
heartbeatChenkTimer = null;
// 自定义 回调函数
callbacks ={}
// 标识:是否连接成功 , 记录重试的次数,重新连接尝试的次数
connected = false;
printerIsRead = false;
sendRetryCount = 0;
connectRetryCount = 0;
static instance = null;
constructor(custNo) {
this.instance = null
this.custNo=custNo
}
static getInstance(custNo) {
if (!this.instance) {
this.instance = new XdLbsUniSdk(custNo)
}
return this.instance
}
// 外部方法----------------------------------------------------------------
init(deviceNo){
// 初始化参数建立连接
// this.token=getToken();
if(this.deviceNo==null){
this.deviceNo=deviceNo;
this.connect();
this.start();
this.initBatteryInfo();
this.initDeviceInfo();
// this.initBackgroundTask();
// init lbs
this.maximumAge = Number(this.LBS_UP_FREQ) * Number(1000);
this.startLbs(this.maximumAge);
}
}
setOnOpen(callback){
this.onOpenCallback.push(callback);
if(this.connected){
if(callback!=null){
callback();
}
}
}
setOnClose(callback){
this.onCloseCallback.push(callback);
if(!this.connected){
if(callback!=null){
callback();
}
}
}
setOnError(callback){
this.onErrorCallback.push(callback);
}
setOnMessage(callback){
this.onMessageCallback.push(callback);
if(this.connected){
if(callback!=null){
callback();
}
}
}
getRequestId() {
let requestId = 'req' + new Date().getTime().toString(36) + Math.random().toString(36).substring(2, 9);
return requestId;
}
//--内部方法--------------------------------------------------------------
// 连接服务器的方法
connect() {
const that=this;
if (!this.ws || this.getWSReadyState() === this.WS_CLOSING || this.getWSReadyState() === this.WS_CLOSE) {
try {
this.ws = uni.connectSocket({
url: this.WS_URL,
header: {
'content-type': 'application/json'
},
protocols: ['protocol1'],
success(res){
// console.error("connectSocket success====");
console.log('WebSocket 连接启动成功');
that.connectRetryCount = 0; // 重置重连计数
},
fail(err) {
console.error("connectSocket fail====", err)
setTimeout(reConnectSock, 3000)
}
})
this.ws.onError((err)=> {
console.log('ws.onError: ', JSON.stringify(err));
// console.log("ws onerror!");
if(this.onErrorCallback.length>0){
this.onErrorCallback.forEach(callback=>{
if(callback!=null){
callback(err);
}
})
}
})
this.ws.onOpen((res)=>{
console.log("===>ws onopen!");
this.connected = true
this.connectRetryCount = 0
// 注册客户端
this.register()
if(this.onOpenCallback.length>0){
this.onOpenCallback.forEach(callback=>{
if(callback!=null){
callback();
}
})
}
})
this.ws.onClose((res = {})=> {
console.log('ws.onClose: ', JSON.stringify(res));
this.connected = false;
this.connectRetryCount++;
if(this.connectRetryCount>120){
this.connectRetryCount=0;
}
if(this.onCloseCallback.length>0){
this.onCloseCallback.forEach(callback=>{
if(callback!=null){
callback();
}
})
}
// * this.connectRetryCount
setTimeout(() => {
this.connect()
}, 1000 )
})
this.ws.onMessage(function (res) {
console.log('==>ws onmessage:' + res.data)
let resData = JSON.parse(res.data)
if(resData.code == 200){
let resCmd=resData.data;
if(resCmd.cmdType=='LbsRegister'){
that.msisdn = resCmd.msisdn
}
}
// if(this.onMessageCallback.length>0){
// this.onMessageCallback.forEach(callback=>{
// if(callback!=null){
// callback(e.data);
// }
// })
// }
})
} catch (ex) {
setTimeout(() => {
this.connect()
}, 60000 )
}
}
return this.ws;
}
jsonToObj(json){
return JSON.parse(json)
}
objToJson(obj){
return JSON.stringify(obj)
}
/**
* readyState->0:尚未建立连接;1:已经建立连接;2:正在关闭;3:已经关闭或不可用
* 0:连接正在建立
1:连接已建立,可以通信
2:连接正在关闭
3:连接已关闭或无法打开
* @param thisWs
* @returns {*}
*/
getWSReadyState() {
if (this.ws.readyState !== undefined) {
return this.ws.readyState;
}
return this.WS_INIT;
};
// 发送数据的方法
send(data) {
// console.log("send:"+data)
if (this.getWSReadyState() === this.WS_OPEN ) {
this.sendRetryCount = 0
this.ws.send({data:data})
return 1;
} else {
console.log("Ws is abnormal,send faild!!")
return -1
}
}
// 关闭socket连接
close() {
if (this.ws) {
this.ws.close();
this.connected = false; // 更新连接状态
clearInterval(this.heartbeatChenkTimer); // 清除心跳检测定时器
clearInterval(this.registerCheckTimer);
this.closeLbs();
}
}
// 开启检测
start() {
const that=this;
this.heartbeatChenkTimer = setInterval(() => {
that.connect()
}, 600000);
this.registerCheckTimer = setInterval(() => {
this.register();
}, 60000);
}
// 注册客户端
register(){
if(this.deviceNo != null && this.msisdn == null){
let postData = {
cmdType:"LbsRegister",
custNo:this.custNo,
deviceNo:this.deviceNo,
reqId:this.getRequestId(),
// deviceInfo:this.deviceInfo
}
const jsonString = JSON.stringify(postData)
let base64Str=btoa(jsonString)
this.send(base64Str);
}
}
initBackgroundTask() {
const platform = uni.getSystemInfoSync().platform;
if (platform === 'android') {
startBackgroundService();
// 注册后台定时任务
registerBackgroundFetch();
}
}
startBackgroundService() {
const platform = uni.getSystemInfoSync().platform;
if (platform === 'android') {
const Intent = plus.android.importClass('android.content.Intent');
const mainActivity = plus.android.runtimeMainActivity();
const intent = new Intent(mainActivity, mainActivity.getClass());
// 设置服务为前台服务
const Notification = plus.android.importClass('android.app.Notification');
const NotificationManager = plus.android.importClass('android.app.NotificationManager');
const nm = mainActivity.getSystemService(mainActivity.NOTIFICATION_SERVICE);
const notification = new Notification();
notification.tickerText = 'App 正在后台运行';
notification.icon = plus.android.R.drawable.ic_launcher;
mainActivity.startForegroundService(intent);
mainActivity.startService(intent);
}
}
registerBackgroundFetch() {
const bgFetchManager = uni.getBackgroundFetchManager();
bgFetchManager.register({
interval: 15 // 分钟
}, async () => {
try {
// 执行数据同步
// const result = await syncDataWithServer();
console.log('后台同步成功:', result);
} catch (err) {
console.error('后台同步失败:', err);
}
});
}
initDeviceInfo() {
const that=this
if(that.deviceInfo==null){
that.deviceInfo = uni.getSystemInfoSync()
}
}
//检测是否开启系统定位权限
hasLocationPermission() {
let system = uni.getSystemInfoSync();
if (system.platform === 'android') { //安卓
let context = plus.android.importClass("android.content.Context");
let locationManager = plus.android.importClass("android.location.LocationManager");
let main = plus.android.runtimeMainActivity();
let service = main.getSystemService(context.LOCATION_SERVICE);
//已开启系统定位服务功能
if (service.isProviderEnabled(locationManager.GPS_PROVIDER)) return true;
else { //未开启引导开启
uni.showModal({
title: '友情提示',
content: '请开启位置服务功能',
success: e => {
if (e.confirm) {
//打开手机系统gps定位设置页面
let Intent = plus.android.importClass('android.content.Intent');
let Settings = plus.android.importClass('android.provider.Settings');
let intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
main.startActivity(intent);
}
}
})
}
} else if (system.platform === 'ios') { //ios
let cllocationManger = plus.ios.import("CLLocationManager");
let enable = cllocationManger.locationServicesEnabled();
let status = cllocationManger.authorizationStatus();
plus.ios.deleteObject(cllocationManger);
if (enable && status != 2) return true; //已开启定位功能
else {
uni.showModal({
title: '友情提示',
content: '请前往设置-定位服务打开定位服务功能',
success: e => {
if (e.confirm) {
let UIApplication = plus.ios.import("UIApplication");
let application = UIApplication.sharedApplication();
let NSURL = plus.ios.import("NSURL");
let setting = NSURL.URLWithString("app-settings:");
application.openURL(setting);
plus.ios.deleteObject(setting);
plus.ios.deleteObject(NSURL);
plus.ios.deleteObject(application);
}
}
});
}
}
return false;
}
startLbs(maximumAge = 60*1000) {
const that=this;
console.log("==>maximumAge:",maximumAge)
// 先关闭再启动
this.closeLbs();
if (this.hasLocationPermission()) { //有定位权限
that.lbsWatcherId = plus.geolocation.watchPosition((position) => {
let coords=position.coords
if(that.deviceNo != null && that.msisdn != null){
let reqId=that.getRequestId();
let heading=parseFloat(coords.heading+'').toFixed(0);
let postData = {
cmdType:"LbsPush",
custNo:that.custNo,
deviceNo:that.deviceNo,
reqId:reqId,
msisdn:that.msisdn,
longitude:coords.longitude,
latitude:coords.latitude,
altitude:coords.altitude,
heading:heading,
speed:coords.speed,
altitudeAccuracy:coords.altitudeAccuracy,
battaryRate:that.batteryInfo.level
}
const jsonString = JSON.stringify(postData)
let base64Str=btoa(jsonString)
that.send(base64Str);
}
}, function(e) {
console.log(e, '定位失败');
}, {
maximumAge, //获取位置间隔时间,在不同定位模块下支持范围值可能不同,如百度定位模块的间隔范围为大于等于1秒,如果设置的值小于最小值则使用最小值。iOS平台根据设备位置变化自动计算回调更新的间隔时间。
// provider: 'amap', //优先使用定位模块,“system”:表示系统定位模块,支持wgs84坐标系; “baidu”:表示百度定位模块,支持gcj02/bd09/bd09ll坐标系; “amap”:表示高德定位模板,支持gcj02坐标系,默认值按以下优先顺序获取(amap>baidu>system)
// timeout: 10000, //定位超时
enableHighAccuracy: true,//高精确度获取位置信息
coordsType:"wgs84",//坐标系类型, “wgs84”:表示WGS-84坐标系; “gcj02”:表示国测局经纬度坐标系,"bd09":百度地图使用的坐标系
//geocode:false//是否解析地址
});
}
}
async initBatteryInfo() {
const that=this;
try {
this.batteryInfo = {
level:100,
isCharging:0
}
} catch (err) {
console.error('初始化电量失败:', err);
}
}
async initBatteryInfoOld() {
const that=this;
try {
this.batteryInfo = await uni.getBatteryInfo();
console.log('电量信息已缓存:', this.batteryInfo);
// 监听电量变化,实时更新缓存
uni.onBatteryInfoChange(info => {
that.batteryInfo = info;
console.log('电量变化:', this.batteryInfo);
});
} catch (err) {
console.error('初始化电量失败:', err);
}
}
// 同步获取缓存的电量
getBatteryLevel() {
return this.batteryInfo?.level ?? -1;
}
//关闭定位功能
closeLbs() {
if(this.lbsWatcherId!=null){
plus.geolocation.clearWatch(this.lbsWatcherId)
this.lbsWatcherId=null;
}
}
}
export default XdLbsUniSdk;