2025-09-12 20:08:42 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 智能项圈设备模型
|
|
|
|
|
|
* @file IotXqClient.js
|
|
|
|
|
|
* @description 智能项圈设备数据模型,对应iot_xq_client表
|
|
|
|
|
|
*/
|
|
|
|
|
|
const { DataTypes, Model } = require('sequelize');
|
|
|
|
|
|
const { sequelize } = require('../config/database-simple');
|
|
|
|
|
|
|
|
|
|
|
|
class IotXqClient extends Model {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取设备状态文本
|
|
|
|
|
|
*/
|
|
|
|
|
|
getStatusText() {
|
|
|
|
|
|
const statusMap = {
|
|
|
|
|
|
0: '离线',
|
|
|
|
|
|
1: '在线',
|
|
|
|
|
|
2: '报警',
|
|
|
|
|
|
3: '维护'
|
|
|
|
|
|
};
|
2025-09-23 18:13:11 +08:00
|
|
|
|
return statusMap[this.is_connect] || '未知';
|
2025-09-12 20:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取设备状态颜色
|
|
|
|
|
|
*/
|
|
|
|
|
|
getStatusColor() {
|
|
|
|
|
|
const colorMap = {
|
|
|
|
|
|
0: 'red', // 离线
|
|
|
|
|
|
1: 'green', // 在线
|
|
|
|
|
|
2: 'orange', // 报警
|
|
|
|
|
|
3: 'blue' // 维护
|
|
|
|
|
|
};
|
2025-09-23 18:13:11 +08:00
|
|
|
|
return colorMap[this.is_connect] || 'default';
|
2025-09-12 20:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取GPS信号强度等级(1-5星)
|
|
|
|
|
|
*/
|
|
|
|
|
|
getGpsSignalLevel() {
|
|
|
|
|
|
const nsat = parseInt(this.nsat) || 0;
|
|
|
|
|
|
if (nsat >= 8) return 5;
|
|
|
|
|
|
if (nsat >= 6) return 4;
|
|
|
|
|
|
if (nsat >= 4) return 3;
|
|
|
|
|
|
if (nsat >= 2) return 2;
|
|
|
|
|
|
if (nsat >= 1) return 1;
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取电池电量百分比
|
|
|
|
|
|
*/
|
|
|
|
|
|
getBatteryPercent() {
|
|
|
|
|
|
const battery = parseFloat(this.battery) || 0;
|
|
|
|
|
|
// 假设电池电压范围是3.0V-4.2V
|
|
|
|
|
|
if (battery >= 4.2) return 100;
|
|
|
|
|
|
if (battery <= 3.0) return 0;
|
|
|
|
|
|
return Math.round(((battery - 3.0) / 1.2) * 100);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取体温数值
|
|
|
|
|
|
*/
|
|
|
|
|
|
getTemperatureValue() {
|
|
|
|
|
|
return parseFloat(this.temperature) || 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断是否低电量
|
|
|
|
|
|
*/
|
|
|
|
|
|
isLowBattery() {
|
|
|
|
|
|
return this.getBatteryPercent() < 20;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断是否需要维护
|
|
|
|
|
|
*/
|
|
|
|
|
|
needsMaintenance() {
|
|
|
|
|
|
return this.state === 3 || !this.is_connect || this.isLowBattery();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取最后更新时间
|
|
|
|
|
|
*/
|
|
|
|
|
|
getLastUpdateTime() {
|
|
|
|
|
|
if (this.uptime) {
|
|
|
|
|
|
return new Date(this.uptime * 1000).toLocaleString('zh-CN');
|
|
|
|
|
|
}
|
|
|
|
|
|
return '未知';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化模型
|
|
|
|
|
|
IotXqClient.init({
|
|
|
|
|
|
id: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
primaryKey: true,
|
|
|
|
|
|
autoIncrement: true,
|
|
|
|
|
|
comment: '项圈设备ID'
|
|
|
|
|
|
},
|
|
|
|
|
|
org_id: {
|
|
|
|
|
|
type: DataTypes.INTEGER.UNSIGNED,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '组织ID'
|
|
|
|
|
|
},
|
|
|
|
|
|
uid: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '用户ID'
|
|
|
|
|
|
},
|
|
|
|
|
|
deviceId: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '设备编号'
|
|
|
|
|
|
},
|
|
|
|
|
|
sn: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '设备序列号'
|
|
|
|
|
|
},
|
|
|
|
|
|
sort: {
|
|
|
|
|
|
type: DataTypes.TINYINT.UNSIGNED,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 1,
|
|
|
|
|
|
comment: '排序'
|
|
|
|
|
|
},
|
|
|
|
|
|
state: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '设备状态'
|
|
|
|
|
|
},
|
|
|
|
|
|
longitude: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '经度'
|
|
|
|
|
|
},
|
|
|
|
|
|
latitude: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '纬度'
|
|
|
|
|
|
},
|
|
|
|
|
|
altitude: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '海拔'
|
|
|
|
|
|
},
|
|
|
|
|
|
gps_state: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: 'GPS状态'
|
|
|
|
|
|
},
|
|
|
|
|
|
nsat: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: 'GPS卫星数量'
|
|
|
|
|
|
},
|
|
|
|
|
|
rsrp: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '信号强度'
|
|
|
|
|
|
},
|
|
|
|
|
|
battery: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '电池电量'
|
|
|
|
|
|
},
|
|
|
|
|
|
temperature: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '体温'
|
|
|
|
|
|
},
|
|
|
|
|
|
steps: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '步数'
|
|
|
|
|
|
},
|
|
|
|
|
|
acc_x: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: 'X轴加速度'
|
|
|
|
|
|
},
|
|
|
|
|
|
acc_y: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: 'Y轴加速度'
|
|
|
|
|
|
},
|
|
|
|
|
|
acc_z: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: 'Z轴加速度'
|
|
|
|
|
|
},
|
|
|
|
|
|
bandge_status: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '设备佩戴状态'
|
|
|
|
|
|
},
|
|
|
|
|
|
ver: {
|
|
|
|
|
|
type: DataTypes.STRING(50),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '固件版本'
|
|
|
|
|
|
},
|
|
|
|
|
|
time: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '设备时间戳'
|
|
|
|
|
|
},
|
|
|
|
|
|
uptime: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '上传时间戳'
|
|
|
|
|
|
},
|
|
|
|
|
|
distribute_time: {
|
|
|
|
|
|
type: DataTypes.INTEGER.UNSIGNED,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '分发时间'
|
|
|
|
|
|
},
|
|
|
|
|
|
zenowalk: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '零步数'
|
|
|
|
|
|
},
|
|
|
|
|
|
zenotime: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '零时间'
|
|
|
|
|
|
},
|
|
|
|
|
|
bank_item_id: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '栏位项目ID'
|
|
|
|
|
|
},
|
|
|
|
|
|
bank_house: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '栏舍编号'
|
|
|
|
|
|
},
|
|
|
|
|
|
bank_lanwei: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '栏位编号'
|
|
|
|
|
|
},
|
|
|
|
|
|
bank_place: {
|
|
|
|
|
|
type: DataTypes.TINYINT,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '位置编号'
|
|
|
|
|
|
},
|
|
|
|
|
|
is_home: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 1,
|
|
|
|
|
|
comment: '是否在家'
|
|
|
|
|
|
},
|
|
|
|
|
|
fence_id: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '围栏ID'
|
|
|
|
|
|
},
|
|
|
|
|
|
y_steps: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '昨日步数'
|
|
|
|
|
|
},
|
|
|
|
|
|
is_wear: {
|
|
|
|
|
|
type: DataTypes.TINYINT.UNSIGNED,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '是否佩戴'
|
|
|
|
|
|
},
|
|
|
|
|
|
is_temperature: {
|
|
|
|
|
|
type: DataTypes.TINYINT.UNSIGNED,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '是否测温'
|
|
|
|
|
|
},
|
|
|
|
|
|
is_connect: {
|
|
|
|
|
|
type: DataTypes.TINYINT.UNSIGNED,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 1,
|
|
|
|
|
|
comment: '是否连接'
|
|
|
|
|
|
},
|
|
|
|
|
|
source_id: {
|
|
|
|
|
|
type: DataTypes.BIGINT,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '数据源ID'
|
|
|
|
|
|
},
|
|
|
|
|
|
loctime: {
|
|
|
|
|
|
type: DataTypes.STRING(20),
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '定位时间'
|
|
|
|
|
|
},
|
|
|
|
|
|
expire_time: {
|
|
|
|
|
|
type: DataTypes.INTEGER.UNSIGNED,
|
|
|
|
|
|
allowNull: false,
|
|
|
|
|
|
defaultValue: 0,
|
|
|
|
|
|
comment: '过期时间'
|
|
|
|
|
|
},
|
|
|
|
|
|
subType: {
|
|
|
|
|
|
type: DataTypes.INTEGER,
|
|
|
|
|
|
allowNull: true,
|
|
|
|
|
|
comment: '子类型'
|
|
|
|
|
|
}
|
|
|
|
|
|
}, {
|
|
|
|
|
|
sequelize,
|
|
|
|
|
|
modelName: 'IotXqClient',
|
|
|
|
|
|
tableName: 'iot_xq_client',
|
|
|
|
|
|
timestamps: false, // 该表没有created_at和updated_at字段
|
|
|
|
|
|
indexes: [
|
|
|
|
|
|
{
|
|
|
|
|
|
fields: ['uid']
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
fields: ['sn']
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
fields: ['ver']
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
fields: ['fence_id']
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
fields: ['source_id']
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = IotXqClient;
|