461 lines
13 KiB
JavaScript
461 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();
|
|||
|
|
|
|||
|
|
// 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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 开启检测
|
|||
|
|
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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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 postData = {
|
|||
|
|
cmdType:"LbsPush",
|
|||
|
|
custNo:that.custNo,
|
|||
|
|
deviceNo:that.deviceNo,
|
|||
|
|
reqId:that.getRequestId(),
|
|||
|
|
msisdn:that.msisdn,
|
|||
|
|
longitude:coords.longitude,
|
|||
|
|
latitude:coords.latitude,
|
|||
|
|
altitude:coords.altitude,
|
|||
|
|
heading:coords.heading,
|
|||
|
|
speed:coords.speed,
|
|||
|
|
altitudeAccuracy:coords.altitudeAccuracy,
|
|||
|
|
battaryRate:-1,
|
|||
|
|
}
|
|||
|
|
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//是否解析地址
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 应用启动时初始化
|
|||
|
|
// initBatteryInfo() {
|
|||
|
|
// const env = uni.getEnv();
|
|||
|
|
// console.log('==>initBatteryInfo==env=>:', env)
|
|||
|
|
// if (env === uni.ENV_TYPE.APP) {
|
|||
|
|
// // App 端使用 uni API
|
|||
|
|
// return uni.getBatteryInfo({
|
|||
|
|
// success: (res) => console.log('App 电量:', res),
|
|||
|
|
// fail: (err) => console.error('App 获取失败:', err)
|
|||
|
|
// });
|
|||
|
|
// } else if (env === uni.ENV_TYPE.WECHAT) {
|
|||
|
|
// // 微信小程序使用 wx API(兼容处理)
|
|||
|
|
// return wx.getBatteryInfo({
|
|||
|
|
// success: (res) => console.log('微信电量:', res),
|
|||
|
|
// fail: (err) => console.error('微信获取失败:', err)
|
|||
|
|
// });
|
|||
|
|
// } else if (env === uni.ENV_TYPE.H5) {
|
|||
|
|
// // H5 端使用浏览器 API
|
|||
|
|
// if (navigator.getBattery) {
|
|||
|
|
// return navigator.getBattery().then(battery => {
|
|||
|
|
// console.log('H5 电量:', {
|
|||
|
|
// level: Math.round(battery.level * 100),
|
|||
|
|
// isCharging: battery.charging
|
|||
|
|
// });
|
|||
|
|
// }).catch(err => console.error('H5 获取失败:', err));
|
|||
|
|
// } else {
|
|||
|
|
// console.warn('当前浏览器不支持电池 API');
|
|||
|
|
// }
|
|||
|
|
// } else {
|
|||
|
|
// console.warn('当前平台不支持获取电池信息');
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
async initBatteryInfo() {
|
|||
|
|
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 cachedBatteryInfo?.level ?? -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//关闭定位功能
|
|||
|
|
closeLbs() {
|
|||
|
|
if(this.lbsWatcherId!=null){
|
|||
|
|
plus.geolocation.clearWatch(this.lbsWatcherId)
|
|||
|
|
this.lbsWatcherId=null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default XdLbsUniSdk;
|