494 lines
13 KiB
JavaScript
494 lines
13 KiB
JavaScript
/*
|
||
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;
|