From f557cca7cccdc1f7ae0cffc3ee4fcb10152fbf8b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=B0=A2=E6=B4=AA=E9=BE=99?= <599179587@qq.com>
Date: Thu, 6 Jul 2017 18:12:01 +0800
Subject: [PATCH] =?UTF-8?q?Socket=E9=A1=B9=E7=9B=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 1 +
nb-configuration.xml | 19 +
pom.xml | 227 +++++++
src/main/java/com/ifish/bean/LoginRecord.java | 49 ++
src/main/java/com/ifish/bean/Tbl_Device.java | 508 ++++++++++++++
.../com/ifish/bean/Tbl_Device_Statistics.java | 630 ++++++++++++++++++
.../java/com/ifish/bean/Tbl_Device_User.java | 293 ++++++++
.../java/com/ifish/bean/Tbl_Factory_List.java | 125 ++++
.../com/ifish/bean/Tbl_HardWare_Type.java | 437 ++++++++++++
.../java/com/ifish/bean/Tbl_Push_List.java | 465 +++++++++++++
src/main/java/com/ifish/bean/Tbl_User.java | 557 ++++++++++++++++
.../java/com/ifish/config/MinaConfig.java | 139 ++++
.../config/MyWSServletContextListener.java | 14 +
.../java/com/ifish/config/MybatisConfig.java | 86 +++
.../java/com/ifish/config/RedisConfig.java | 58 ++
.../java/com/ifish/config/RootConfig.java | 26 +
.../com/ifish/config/WebAppInitializer.java | 46 ++
src/main/java/com/ifish/config/WebConfig.java | 59 ++
.../java/com/ifish/enums/PushTypeEnum.java | 33 +
.../com/ifish/enums/SubDirectoryEnum.java | 45 ++
.../java/com/ifish/helper/DeviceHelperI.java | 41 ++
.../java/com/ifish/helper/UserHelperI.java | 20 +
.../com/ifish/socket/codeFactory/Context.java | 58 ++
.../codeFactory/ServerCodecFactory.java | 31 +
.../socket/codeFactory/ServerDecode.java | 385 +++++++++++
.../socket/codeFactory/ServerEncode.java | 137 ++++
.../com/ifish/socket/config/ExecuteJob.java | 119 ++++
.../com/ifish/socket/config/JobFactory.java | 31 +
.../socket/config/MinaServerHandler.java | 126 ++++
.../socket/config/MyInetSocketAddress.java | 53 ++
.../com/ifish/socket/config/ScheduleJob.java | 114 ++++
.../com/ifish/socket/config/SomeServer.java | 364 ++++++++++
.../socket/model/DeviceResponseLength99.java | 500 ++++++++++++++
.../com/ifish/socket/model/HeadModel.java | 80 +++
.../java/com/ifish/socket/model/JobGroup.java | 107 +++
.../com/ifish/socket/model/OrderModel.java | 101 +++
.../receive/APPLoginResponseLength26.java | 41 ++
.../receive/DeviceLoginResponseLength25.java | 31 +
.../receive/ServerHeartbeatLength17.java | 21 +
.../model/send/APPLoginContextLength25.java | 30 +
.../send/DeviceLoginContextLength24.java | 61 ++
.../model/send/ModelVersionLength22.java | 60 ++
.../model/send/ModelVersionLength38.java | 111 +++
.../model/send/TemperatureAlarmLength22.java | 51 ++
.../model/send/TemperatureSwitchLength22.java | 51 ++
.../model/send/UpgradeVersionLength78.java | 41 ++
.../ifish/socket/webService/MyService.java | 54 ++
.../ifish/socket/webService/ServiceBean.java | 19 +
src/main/java/com/ifish/util/ByteUtil.java | 196 ++++++
.../java/com/ifish/util/IfishFilePath.java | 113 ++++
src/main/java/com/ifish/util/IfishUtil.java | 454 +++++++++++++
.../java/com/ifish/util/JdbcProperties.java | 61 ++
src/main/java/com/ifish/util/RedisKey.java | 78 +++
src/main/resources/fdfs_client_ifish7.conf | 7 +
.../resources/fdfs_client_zhangxinyanv5.conf | 8 +
src/main/resources/jdbc.properties | 40 ++
src/main/resources/property.properties | 44 ++
src/main/webapp/META-INF/context.xml | 2 +
.../WEB-INF/lib/fastdfs-client-java-1.25.jar | Bin 0 -> 91061 bytes
src/main/webapp/index.jsp | 13 +
60 files changed, 7671 insertions(+)
create mode 100644 .gitignore
create mode 100644 nb-configuration.xml
create mode 100644 pom.xml
create mode 100644 src/main/java/com/ifish/bean/LoginRecord.java
create mode 100644 src/main/java/com/ifish/bean/Tbl_Device.java
create mode 100644 src/main/java/com/ifish/bean/Tbl_Device_Statistics.java
create mode 100644 src/main/java/com/ifish/bean/Tbl_Device_User.java
create mode 100644 src/main/java/com/ifish/bean/Tbl_Factory_List.java
create mode 100644 src/main/java/com/ifish/bean/Tbl_HardWare_Type.java
create mode 100644 src/main/java/com/ifish/bean/Tbl_Push_List.java
create mode 100644 src/main/java/com/ifish/bean/Tbl_User.java
create mode 100644 src/main/java/com/ifish/config/MinaConfig.java
create mode 100644 src/main/java/com/ifish/config/MyWSServletContextListener.java
create mode 100644 src/main/java/com/ifish/config/MybatisConfig.java
create mode 100644 src/main/java/com/ifish/config/RedisConfig.java
create mode 100644 src/main/java/com/ifish/config/RootConfig.java
create mode 100644 src/main/java/com/ifish/config/WebAppInitializer.java
create mode 100644 src/main/java/com/ifish/config/WebConfig.java
create mode 100644 src/main/java/com/ifish/enums/PushTypeEnum.java
create mode 100644 src/main/java/com/ifish/enums/SubDirectoryEnum.java
create mode 100644 src/main/java/com/ifish/helper/DeviceHelperI.java
create mode 100644 src/main/java/com/ifish/helper/UserHelperI.java
create mode 100644 src/main/java/com/ifish/socket/codeFactory/Context.java
create mode 100644 src/main/java/com/ifish/socket/codeFactory/ServerCodecFactory.java
create mode 100644 src/main/java/com/ifish/socket/codeFactory/ServerDecode.java
create mode 100644 src/main/java/com/ifish/socket/codeFactory/ServerEncode.java
create mode 100644 src/main/java/com/ifish/socket/config/ExecuteJob.java
create mode 100644 src/main/java/com/ifish/socket/config/JobFactory.java
create mode 100644 src/main/java/com/ifish/socket/config/MinaServerHandler.java
create mode 100644 src/main/java/com/ifish/socket/config/MyInetSocketAddress.java
create mode 100644 src/main/java/com/ifish/socket/config/ScheduleJob.java
create mode 100644 src/main/java/com/ifish/socket/config/SomeServer.java
create mode 100644 src/main/java/com/ifish/socket/model/DeviceResponseLength99.java
create mode 100644 src/main/java/com/ifish/socket/model/HeadModel.java
create mode 100644 src/main/java/com/ifish/socket/model/JobGroup.java
create mode 100644 src/main/java/com/ifish/socket/model/OrderModel.java
create mode 100644 src/main/java/com/ifish/socket/model/receive/APPLoginResponseLength26.java
create mode 100644 src/main/java/com/ifish/socket/model/receive/DeviceLoginResponseLength25.java
create mode 100644 src/main/java/com/ifish/socket/model/receive/ServerHeartbeatLength17.java
create mode 100644 src/main/java/com/ifish/socket/model/send/APPLoginContextLength25.java
create mode 100644 src/main/java/com/ifish/socket/model/send/DeviceLoginContextLength24.java
create mode 100644 src/main/java/com/ifish/socket/model/send/ModelVersionLength22.java
create mode 100644 src/main/java/com/ifish/socket/model/send/ModelVersionLength38.java
create mode 100644 src/main/java/com/ifish/socket/model/send/TemperatureAlarmLength22.java
create mode 100644 src/main/java/com/ifish/socket/model/send/TemperatureSwitchLength22.java
create mode 100644 src/main/java/com/ifish/socket/model/send/UpgradeVersionLength78.java
create mode 100644 src/main/java/com/ifish/socket/webService/MyService.java
create mode 100644 src/main/java/com/ifish/socket/webService/ServiceBean.java
create mode 100644 src/main/java/com/ifish/util/ByteUtil.java
create mode 100644 src/main/java/com/ifish/util/IfishFilePath.java
create mode 100644 src/main/java/com/ifish/util/IfishUtil.java
create mode 100644 src/main/java/com/ifish/util/JdbcProperties.java
create mode 100644 src/main/java/com/ifish/util/RedisKey.java
create mode 100644 src/main/resources/fdfs_client_ifish7.conf
create mode 100644 src/main/resources/fdfs_client_zhangxinyanv5.conf
create mode 100644 src/main/resources/jdbc.properties
create mode 100644 src/main/resources/property.properties
create mode 100644 src/main/webapp/META-INF/context.xml
create mode 100644 src/main/webapp/WEB-INF/lib/fastdfs-client-java-1.25.jar
create mode 100644 src/main/webapp/index.jsp
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9f97022
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+target/
\ No newline at end of file
diff --git a/nb-configuration.xml b/nb-configuration.xml
new file mode 100644
index 0000000..99174dc
--- /dev/null
+++ b/nb-configuration.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+ 1.6-web
+ Tomcat
+
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..80dba0b
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,227 @@
+
+ 4.0.0
+
+ com.ifish
+ IfishSocketEnglish
+ 1.0
+ war
+
+ IfishSocketEnglish
+
+
+ ${project.build.directory}/endorsed
+ UTF-8
+
+
+
+
+
+ com.sun.xml.ws
+ jaxws-tools
+ 2.2.10
+ pom
+
+
+
+ org.json
+ json
+ 20170516
+
+
+
+ org.apache.mina
+ mina-core
+ 2.0.16
+
+
+
+ org.quartz-scheduler
+ quartz
+ 2.3.0
+
+
+
+ org.csource
+ fastdfs-client-java
+ 1.25
+ system
+ ${basedir}/src/main/webapp/WEB-INF/lib/fastdfs-client-java-1.25.jar
+
+
+ cn.jpush.api
+ jpush-client
+ 3.2.17
+
+
+ org.apache.commons
+ commons-lang3
+ 3.5
+ jar
+
+
+ org.codehaus.jackson
+ jackson-mapper-asl
+ 1.9.13
+ jar
+
+
+ com.alibaba
+ fastjson
+ 1.2.28
+ jar
+
+
+ org.springframework.data
+ spring-data-redis
+ 1.8.4.RELEASE
+ jar
+
+
+ org.apache.commons
+ commons-pool2
+ 2.4.2
+ jar
+
+
+ redis.clients
+ jedis
+ 2.9.0
+ jar
+
+
+ c3p0
+ c3p0
+ 0.9.1.2
+ jar
+
+
+ javax
+ javaee-web-api
+ 6.0
+ provided
+
+
+
+ org.springframework
+ spring-context
+ 4.3.9.RELEASE
+
+
+
+ org.springframework
+ spring-beans
+ 4.3.9.RELEASE
+
+
+
+ org.springframework
+ spring-core
+ 4.3.9.RELEASE
+
+
+
+ org.springframework
+ spring-web
+ 4.3.9.RELEASE
+
+
+
+ org.springframework
+ spring-webmvc
+ 4.3.8.RELEASE
+ jar
+
+
+
+ org.springframework
+ spring-jdbc
+ 4.3.9.RELEASE
+
+
+
+ org.mybatis
+ mybatis
+ 3.4.4
+
+
+
+ org.mybatis
+ mybatis-spring
+ 1.3.1
+
+
+ cn.jpush.api
+ jiguang-common
+ 1.0.3
+
+
+ io.netty
+ netty-all
+ 4.1.6.Final
+ compile
+
+
+ com.google.code.gson
+ gson
+ 2.3
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.13
+ jar
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+ 1.6
+ 1.6
+
+ ${endorsed.dir}
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 2.1.1
+
+ false
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 2.1
+
+
+ validate
+
+ copy
+
+
+ ${endorsed.dir}
+ true
+
+
+ javax
+ javaee-endorsed-api
+ 6.0
+ jar
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/ifish/bean/LoginRecord.java b/src/main/java/com/ifish/bean/LoginRecord.java
new file mode 100644
index 0000000..46f9eb2
--- /dev/null
+++ b/src/main/java/com/ifish/bean/LoginRecord.java
@@ -0,0 +1,49 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.bean;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ *
+ * @author Administrator
+ */
+public class LoginRecord implements Serializable {
+
+ private static final long serialVersionUID = -5292867602998823697L;
+ //ID
+ private Integer recordId;
+ //mac地址
+ private String macAddress;
+ //登录时间
+ private Date loginTime;
+
+ public Integer getRecordId() {
+ return recordId;
+ }
+
+ public void setRecordId(Integer recordId) {
+ this.recordId = recordId;
+ }
+
+ public String getMacAddress() {
+ return macAddress;
+ }
+
+ public void setMacAddress(String macAddress) {
+ this.macAddress = macAddress;
+ }
+
+ public Date getLoginTime() {
+ return loginTime;
+ }
+
+ public void setLoginTime(Date loginTime) {
+ this.loginTime = loginTime;
+ }
+
+}
diff --git a/src/main/java/com/ifish/bean/Tbl_Device.java b/src/main/java/com/ifish/bean/Tbl_Device.java
new file mode 100644
index 0000000..ffcb840
--- /dev/null
+++ b/src/main/java/com/ifish/bean/Tbl_Device.java
@@ -0,0 +1,508 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.bean;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * 设备详情表(tbl_device)
+ *
+ * @author Administrator
+ */
+@Entity
+@Table(name = "tbl_device")
+public class Tbl_Device implements java.io.Serializable {
+
+ /**
+ * 版本号
+ */
+ private static final long serialVersionUID = 3405700970095511149L;
+
+ /**
+ * 设备Id
+ */
+ @Id
+ @Column(name = "device_id", unique = true, nullable = false, length = 10)
+ private Integer deviceId;
+
+ /**
+ * 服务器IP
+ */
+ @Column(name = "server_ip", nullable = true, length = 50)
+ private String serverIp;
+
+ /**
+ * 设备IP
+ */
+ @Column(name = "device_ip", nullable = true, length = 50)
+ private String deviceIp;
+
+ /**
+ * 是否为摄像头:1是,0否
+ */
+ @Column(name = "is_camera", nullable = true, length = 1)
+ private String isCamera;
+
+ /**
+ * 设备Mac地址
+ */
+ @Column(name = "mac_address", unique = true, nullable = true, length = 50)
+ private String macAddress;
+
+ /**
+ * 登陆时间
+ */
+ @Column(name = "login_time", nullable = true)
+ private Date loginTime;
+
+ /**
+ * 是否在黑名单:1不在、0在
+ */
+ @Column(name = "is_blacklist", nullable = true, length = 1)
+ private String isBlacklist;
+
+ /**
+ * 设备型号
+ */
+ @Column(name = "hardware_type", nullable = true, length = 10)
+ private String hardwareType;
+
+ /**
+ * 是否推送
+ */
+ @Column(name = "on_off", nullable = true, length = 1)
+ private String onOff;
+
+ /**
+ * 今天是否提醒:1提醒、0不提醒
+ */
+ @Column(name = "today_remind", nullable = true, length = 1)
+ private String todayRemind;
+
+ /**
+ * 是否开启换水提醒:1开启、0不开启
+ */
+ @Column(name = "water_remind", nullable = true, length = 1)
+ private String waterRemind;
+
+ /**
+ * 换水提醒日期
+ */
+ @Column(name = "remind_date", nullable = true)
+ private Date remindDate;
+
+ /**
+ * 换水周期
+ */
+ @Column(name = "remind_cycle", nullable = true, length = 10)
+ private Integer remindCycle;
+
+ /**
+ * 电子厂代码
+ */
+ @Column(name = "factory_code", nullable = true, length = 20)
+ private String factoryCode;
+
+ /**
+ * 鱼缸场代码
+ */
+ @Column(name = "brand_code", nullable = true, length = 20)
+ private String brandCode;
+
+ /**
+ * 摄像头ID
+ */
+ @Column(name = "camera_id", nullable = true, length = 20)
+ private String cameraId;
+
+ /**
+ * 创建时间
+ */
+ @Column(name = "create_time", nullable = true)
+ private Date createTime;
+
+ /**
+ * 摄像头激活码
+ */
+ @Column(name = "active_code", nullable = true, length = 50)
+ private String activeCode;
+
+ /**
+ * 摄像头激活时间
+ */
+ @Column(name = "active_time", nullable = true)
+ private Date activeTime;
+
+ /**
+ * 修改时间
+ */
+ @Column(name = "update_time", nullable = true)
+ private Date updateTime;
+
+ /**
+ * 获取设备Id
+ *
+ * @return 设备Id
+ */
+ public Integer getDeviceId() {
+ return this.deviceId;
+ }
+
+ /**
+ * 设置设备Id
+ *
+ * @param deviceId 设备Id
+ */
+ public void setDeviceId(Integer deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ /**
+ * 获取服务器IP
+ *
+ * @return 服务器IP
+ */
+ public String getServerIp() {
+ return this.serverIp;
+ }
+
+ /**
+ * 设置服务器IP
+ *
+ * @param serverIp 服务器IP
+ */
+ public void setServerIp(String serverIp) {
+ this.serverIp = serverIp;
+ }
+
+ /**
+ * 获取设备IP
+ *
+ * @return 设备IP
+ */
+ public String getDeviceIp() {
+ return this.deviceIp;
+ }
+
+ /**
+ * 设置设备IP
+ *
+ * @param deviceIp 设备IP
+ */
+ public void setDeviceIp(String deviceIp) {
+ this.deviceIp = deviceIp;
+ }
+
+ /**
+ * 获取是否为摄像头:1是,0否
+ *
+ * @return 是否为摄像头:1是
+ */
+ public String getIsCamera() {
+ return this.isCamera;
+ }
+
+ /**
+ * 设置是否为摄像头:1是,0否
+ *
+ * @param isCamera 是否为摄像头:1是,0否
+ */
+ public void setIsCamera(String isCamera) {
+ this.isCamera = isCamera;
+ }
+
+ /**
+ * 获取设备Mac地址
+ *
+ * @return 设备Mac地址
+ */
+ public String getMacAddress() {
+ return this.macAddress;
+ }
+
+ /**
+ * 设置设备Mac地址
+ *
+ * @param macAddress 设备Mac地址
+ */
+ public void setMacAddress(String macAddress) {
+ this.macAddress = macAddress;
+ }
+
+ /**
+ * 获取登陆时间
+ *
+ * @return 登陆时间
+ */
+ public Date getLoginTime() {
+ return this.loginTime;
+ }
+
+ /**
+ * 设置登陆时间
+ *
+ * @param loginTime 登陆时间
+ */
+ public void setLoginTime(Date loginTime) {
+ this.loginTime = loginTime;
+ }
+
+ /**
+ * 获取是否在黑名单:1不在、0在
+ *
+ * @return 是否在黑名单
+ */
+ public String getIsBlacklist() {
+ return this.isBlacklist;
+ }
+
+ /**
+ * 设置是否在黑名单:1不在、0在
+ *
+ * @param isBlacklist 是否在黑名单:1不在、0在
+ */
+ public void setIsBlacklist(String isBlacklist) {
+ this.isBlacklist = isBlacklist;
+ }
+
+ /**
+ * 获取设备型号
+ *
+ * @return 设备型号
+ */
+ public String getHardwareType() {
+ return this.hardwareType;
+ }
+
+ /**
+ * 设置设备型号
+ *
+ * @param hardwareType 设备型号
+ */
+ public void setHardwareType(String hardwareType) {
+ this.hardwareType = hardwareType;
+ }
+
+ /**
+ * 获取是否推送
+ *
+ * @return 是否推送
+ */
+ public String getOnOff() {
+ return this.onOff;
+ }
+
+ /**
+ * 设置是否推送
+ *
+ * @param onOff 是否推送
+ */
+ public void setOnOff(String onOff) {
+ this.onOff = onOff;
+ }
+
+ /**
+ * 获取今天是否提醒:1提醒、0不提醒
+ *
+ * @return 今天是否提醒
+ */
+ public String getTodayRemind() {
+ return this.todayRemind;
+ }
+
+ /**
+ * 设置今天是否提醒:1提醒、0不提醒
+ *
+ * @param todayRemind 今天是否提醒:1提醒、0不提醒
+ */
+ public void setTodayRemind(String todayRemind) {
+ this.todayRemind = todayRemind;
+ }
+
+ /**
+ * 获取是否开启换水提醒:1开启、0不开启
+ *
+ * @return 是否开启换水提醒
+ */
+ public String getWaterRemind() {
+ return this.waterRemind;
+ }
+
+ /**
+ * 设置是否开启换水提醒:1开启、0不开启
+ *
+ * @param waterRemind 是否开启换水提醒:1开启、0不开启
+ */
+ public void setWaterRemind(String waterRemind) {
+ this.waterRemind = waterRemind;
+ }
+
+ /**
+ * 获取换水提醒日期
+ *
+ * @return 换水提醒日期
+ */
+ public Date getRemindDate() {
+ return this.remindDate;
+ }
+
+ /**
+ * 设置换水提醒日期
+ *
+ * @param remindDate 换水提醒日期
+ */
+ public void setRemindDate(Date remindDate) {
+ this.remindDate = remindDate;
+ }
+
+ /**
+ * 获取换水周期
+ *
+ * @return 换水周期
+ */
+ public Integer getRemindCycle() {
+ return this.remindCycle;
+ }
+
+ /**
+ * 设置换水周期
+ *
+ * @param remindCycle 换水周期
+ */
+ public void setRemindCycle(Integer remindCycle) {
+ this.remindCycle = remindCycle;
+ }
+
+ /**
+ * 获取电子厂代码
+ *
+ * @return 电子厂代码
+ */
+ public String getFactoryCode() {
+ return this.factoryCode;
+ }
+
+ /**
+ * 设置电子厂代码
+ *
+ * @param factoryCode 电子厂代码
+ */
+ public void setFactoryCode(String factoryCode) {
+ this.factoryCode = factoryCode;
+ }
+
+ /**
+ * 获取鱼缸场代码
+ *
+ * @return 鱼缸场代码
+ */
+ public String getBrandCode() {
+ return this.brandCode;
+ }
+
+ /**
+ * 设置鱼缸场代码
+ *
+ * @param brandCode 鱼缸场代码
+ */
+ public void setBrandCode(String brandCode) {
+ this.brandCode = brandCode;
+ }
+
+ /**
+ * 获取摄像头ID
+ *
+ * @return 摄像头ID
+ */
+ public String getCameraId() {
+ return this.cameraId;
+ }
+
+ /**
+ * 设置摄像头ID
+ *
+ * @param cameraId 摄像头ID
+ */
+ public void setCameraId(String cameraId) {
+ this.cameraId = cameraId;
+ }
+
+ /**
+ * 获取创建时间
+ *
+ * @return 创建时间
+ */
+ public Date getCreateTime() {
+ return this.createTime;
+ }
+
+ /**
+ * 设置创建时间
+ *
+ * @param createTime 创建时间
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ /**
+ * 获取摄像头激活码
+ *
+ * @return 摄像头激活码
+ */
+ public String getActiveCode() {
+ return this.activeCode;
+ }
+
+ /**
+ * 设置摄像头激活码
+ *
+ * @param activeCode 摄像头激活码
+ */
+ public void setActiveCode(String activeCode) {
+ this.activeCode = activeCode;
+ }
+
+ /**
+ * 获取摄像头激活时间
+ *
+ * @return 摄像头激活时间
+ */
+ public Date getActiveTime() {
+ return this.activeTime;
+ }
+
+ /**
+ * 设置摄像头激活时间
+ *
+ * @param activeTime 摄像头激活时间
+ */
+ public void setActiveTime(Date activeTime) {
+ this.activeTime = activeTime;
+ }
+
+ /**
+ * 获取修改时间
+ *
+ * @return 修改时间
+ */
+ public Date getUpdateTime() {
+ return this.updateTime;
+ }
+
+ /**
+ * 设置修改时间
+ *
+ * @param updateTime 修改时间
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+}
diff --git a/src/main/java/com/ifish/bean/Tbl_Device_Statistics.java b/src/main/java/com/ifish/bean/Tbl_Device_Statistics.java
new file mode 100644
index 0000000..a5df6aa
--- /dev/null
+++ b/src/main/java/com/ifish/bean/Tbl_Device_Statistics.java
@@ -0,0 +1,630 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.bean;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * 设备统计信息表(tbl_device_statistics)
+ *
+ * @author bianj
+ * @version 1.0.0 2017-06-29
+ */
+@Entity
+@Table(name = "tbl_device_statistics")
+public class Tbl_Device_Statistics implements java.io.Serializable {
+
+ /**
+ * 版本号
+ */
+ private static final long serialVersionUID = 1215383532220649875L;
+
+ /**
+ * id
+ */
+ @Id
+ @Column(name = "id", unique = true, nullable = false, length = 10)
+ private Integer id;
+
+ /**
+ * 设备ID
+ */
+ @Id
+ @Column(name = "device_id", unique = true, nullable = false, length = 10)
+ private Integer deviceId;
+
+ /**
+ * 设备MAC地址
+ */
+ @Column(name = "mac_address", nullable = true, length = 50)
+ private String macAddress;
+
+ /**
+ * 登陆次数
+ */
+ @Column(name = "login_count", nullable = true, length = 11)
+ private int loginCount;
+
+ /**
+ * 最后登陆时间
+ */
+ @Column(name = "login_time", nullable = true)
+ private Date loginTime;
+
+ /**
+ * 首次激活时间
+ */
+ @Column(name = "first_activate", nullable = true)
+ private Date firstActivate;
+
+ /**
+ * 创建时间
+ */
+ @Column(name = "create_time", nullable = true)
+ private Date createTime;
+
+ /**
+ * 是否收费
+ */
+ @Column(name = "is_charge", nullable = true, length = 1)
+ private String isCharge;
+
+ /**
+ * sdk版本
+ */
+ @Column(name = "sdk_version", nullable = true, length = 10)
+ private String sdkVersion;
+
+ /**
+ * sdk时间
+ */
+ @Column(name = "sdk_time", nullable = true)
+ private Date sdkTime;
+
+ /**
+ * 分配日期
+ */
+ @Column(name = "create_date", nullable = true)
+ private Date createDate;
+
+ /**
+ * 是否升级
+ */
+ @Column(name = "is_upgrade", nullable = true, length = 1)
+ private String isUpgrade;
+
+ /**
+ * 更新版本
+ */
+ @Column(name = "upgrade_version", nullable = true, length = 10)
+ private String upgradeVersion;
+
+ /**
+ * 更新时间
+ */
+ @Column(name = "upgrade_time", nullable = true)
+ private Date upgradeTime;
+
+ /**
+ * 授权时间
+ */
+ @Column(name = "authorize_time", nullable = true)
+ private Date authorizeTime;
+
+ /**
+ * 编号
+ */
+ @Column(name = "create_code", nullable = true, length = 50)
+ private String createCode;
+
+ /**
+ * MCU启动次数
+ */
+ @Column(name = "mcu_count", nullable = true, length = 10)
+ private Integer mcuCount;
+
+ /**
+ * 模块启动次数
+ */
+ @Column(name = "module_count", nullable = true, length = 10)
+ private Integer moduleCount;
+
+ /**
+ * 连接路由器次数
+ */
+ @Column(name = "router_count", nullable = true, length = 10)
+ private Integer routerCount;
+
+ /**
+ * 成功连接服务器次数
+ */
+ @Column(name = "server_count", nullable = true, length = 10)
+ private Integer serverCount;
+
+ /**
+ * 尝试连接服务器次数
+ */
+ @Column(name = "server_try_count", nullable = true, length = 10)
+ private Integer serverTryCount;
+
+ /**
+ * mcu版本
+ */
+ @Column(name = "software_version", nullable = true, length = 10)
+ private String softwareVersion;
+
+ /**
+ * 硬件型号
+ */
+ @Column(name = "hardware_type", nullable = true, length = 10)
+ private String hardwareType;
+
+ /**
+ * 电子厂代码
+ */
+ @Column(name = "factory_code", nullable = true, length = 20)
+ private String factoryCode;
+
+ /**
+ * 鱼缸场代码
+ */
+ @Column(name = "brand_code", nullable = true, length = 20)
+ private String brandCode;
+
+ /**
+ * 获取id
+ *
+ * @return id
+ */
+ public Integer getId() {
+ return this.id;
+ }
+
+ /**
+ * 设置id
+ *
+ * @param id id
+ */
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ /**
+ * 获取设备ID
+ *
+ * @return 设备ID
+ */
+ public Integer getDeviceId() {
+ return this.deviceId;
+ }
+
+ /**
+ * 设置设备ID
+ *
+ * @param deviceId 设备ID
+ */
+ public void setDeviceId(Integer deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ /**
+ * 获取设备MAC地址
+ *
+ * @return 设备MAC地址
+ */
+ public String getMacAddress() {
+ return this.macAddress;
+ }
+
+ /**
+ * 设置设备MAC地址
+ *
+ * @param macAddress 设备MAC地址
+ */
+ public void setMacAddress(String macAddress) {
+ this.macAddress = macAddress;
+ }
+
+ /**
+ * 获取登陆次数
+ *
+ * @return 登陆次数
+ */
+ public Integer getLoginCount() {
+ return this.loginCount;
+ }
+
+ /**
+ * 设置登陆次数
+ *
+ * @param loginCount 登陆次数
+ */
+ public void setLoginCount(Integer loginCount) {
+ this.loginCount = loginCount;
+ }
+
+ /**
+ * 获取最后登陆时间
+ *
+ * @return 最后登陆时间
+ */
+ public Date getLoginTime() {
+ return this.loginTime;
+ }
+
+ /**
+ * 设置最后登陆时间
+ *
+ * @param loginTime 最后登陆时间
+ */
+ public void setLoginTime(Date loginTime) {
+ this.loginTime = loginTime;
+ }
+
+ /**
+ * 获取首次激活时间
+ *
+ * @return 首次激活时间
+ */
+ public Date getFirstActivate() {
+ return this.firstActivate;
+ }
+
+ /**
+ * 设置首次激活时间
+ *
+ * @param firstActivate 首次激活时间
+ */
+ public void setFirstActivate(Date firstActivate) {
+ this.firstActivate = firstActivate;
+ }
+
+ /**
+ * 获取创建时间
+ *
+ * @return 创建时间
+ */
+ public Date getCreateTime() {
+ return this.createTime;
+ }
+
+ /**
+ * 设置创建时间
+ *
+ * @param createTime 创建时间
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ /**
+ * 获取是否收费
+ *
+ * @return 是否收费
+ */
+ public String getIsCharge() {
+ return this.isCharge;
+ }
+
+ /**
+ * 设置是否收费
+ *
+ * @param isCharge 是否收费
+ */
+ public void setIsCharge(String isCharge) {
+ this.isCharge = isCharge;
+ }
+
+ /**
+ * 获取sdk版本
+ *
+ * @return sdk版本
+ */
+ public String getSdkVersion() {
+ return this.sdkVersion;
+ }
+
+ /**
+ * 设置sdk版本
+ *
+ * @param sdkVersion sdk版本
+ */
+ public void setSdkVersion(String sdkVersion) {
+ this.sdkVersion = sdkVersion;
+ }
+
+ /**
+ * 获取sdk时间
+ *
+ * @return sdk时间
+ */
+ public Date getSdkTime() {
+ return this.sdkTime;
+ }
+
+ /**
+ * 设置sdk时间
+ *
+ * @param sdkTime sdk时间
+ */
+ public void setSdkTime(Date sdkTime) {
+ this.sdkTime = sdkTime;
+ }
+
+ /**
+ * 获取分配日期
+ *
+ * @return 分配日期
+ */
+ public Date getCreateDate() {
+ return this.createDate;
+ }
+
+ /**
+ * 设置分配日期
+ *
+ * @param createDate 分配日期
+ */
+ public void setCreateDate(Date createDate) {
+ this.createDate = createDate;
+ }
+
+ /**
+ * 获取是否升级
+ *
+ * @return 是否升级
+ */
+ public String getIsUpgrade() {
+ return this.isUpgrade;
+ }
+
+ /**
+ * 设置是否升级
+ *
+ * @param isUpgrade 是否升级
+ */
+ public void setIsUpgrade(String isUpgrade) {
+ this.isUpgrade = isUpgrade;
+ }
+
+ /**
+ * 获取更新版本
+ *
+ * @return 更新版本
+ */
+ public String getUpgradeVersion() {
+ return this.upgradeVersion;
+ }
+
+ /**
+ * 设置更新版本
+ *
+ * @param upgradeVersion 更新版本
+ */
+ public void setUpgradeVersion(String upgradeVersion) {
+ this.upgradeVersion = upgradeVersion;
+ }
+
+ /**
+ * 获取更新时间
+ *
+ * @return 更新时间
+ */
+ public Date getUpgradeTime() {
+ return this.upgradeTime;
+ }
+
+ /**
+ * 设置更新时间
+ *
+ * @param upgradeTime 更新时间
+ */
+ public void setUpgradeTime(Date upgradeTime) {
+ this.upgradeTime = upgradeTime;
+ }
+
+ /**
+ * 获取授权时间
+ *
+ * @return 授权时间
+ */
+ public Date getAuthorizeTime() {
+ return this.authorizeTime;
+ }
+
+ /**
+ * 设置授权时间
+ *
+ * @param authorizeTime 授权时间
+ */
+ public void setAuthorizeTime(Date authorizeTime) {
+ this.authorizeTime = authorizeTime;
+ }
+
+ /**
+ * 获取编号
+ *
+ * @return 编号
+ */
+ public String getCreateCode() {
+ return this.createCode;
+ }
+
+ /**
+ * 设置编号
+ *
+ * @param createCode 编号
+ */
+ public void setCreateCode(String createCode) {
+ this.createCode = createCode;
+ }
+
+ /**
+ * 获取MCU启动次数
+ *
+ * @return MCU启动次数
+ */
+ public Integer getMcuCount() {
+ return this.mcuCount;
+ }
+
+ /**
+ * 设置MCU启动次数
+ *
+ * @param mcuCount MCU启动次数
+ */
+ public void setMcuCount(Integer mcuCount) {
+ this.mcuCount = mcuCount;
+ }
+
+ /**
+ * 获取模块启动次数
+ *
+ * @return 模块启动次数
+ */
+ public Integer getModuleCount() {
+ return this.moduleCount;
+ }
+
+ /**
+ * 设置模块启动次数
+ *
+ * @param moduleCount 模块启动次数
+ */
+ public void setModuleCount(Integer moduleCount) {
+ this.moduleCount = moduleCount;
+ }
+
+ /**
+ * 获取连接路由器次数
+ *
+ * @return 连接路由器次数
+ */
+ public Integer getRouterCount() {
+ return this.routerCount;
+ }
+
+ /**
+ * 设置连接路由器次数
+ *
+ * @param routerCount 连接路由器次数
+ */
+ public void setRouterCount(Integer routerCount) {
+ this.routerCount = routerCount;
+ }
+
+ /**
+ * 获取成功连接服务器次数
+ *
+ * @return 成功连接服务器次数
+ */
+ public Integer getServerCount() {
+ return this.serverCount;
+ }
+
+ /**
+ * 设置成功连接服务器次数
+ *
+ * @param serverCount 成功连接服务器次数
+ */
+ public void setServerCount(Integer serverCount) {
+ this.serverCount = serverCount;
+ }
+
+ /**
+ * 获取尝试连接服务器次数
+ *
+ * @return 尝试连接服务器次数
+ */
+ public Integer getServerTryCount() {
+ return this.serverTryCount;
+ }
+
+ /**
+ * 设置尝试连接服务器次数
+ *
+ * @param serverTryCount 尝试连接服务器次数
+ */
+ public void setServerTryCount(Integer serverTryCount) {
+ this.serverTryCount = serverTryCount;
+ }
+
+ /**
+ * 获取mcu版本
+ *
+ * @return mcu版本
+ */
+ public String getSoftwareVersion() {
+ return this.softwareVersion;
+ }
+
+ /**
+ * 设置mcu版本
+ *
+ * @param softwareVersion mcu版本
+ */
+ public void setSoftwareVersion(String softwareVersion) {
+ this.softwareVersion = softwareVersion;
+ }
+
+ /**
+ * 获取硬件型号
+ *
+ * @return 硬件型号
+ */
+ public String getHardwareType() {
+ return this.hardwareType;
+ }
+
+ /**
+ * 设置硬件型号
+ *
+ * @param hardwareType 硬件型号
+ */
+ public void setHardwareType(String hardwareType) {
+ this.hardwareType = hardwareType;
+ }
+
+ /**
+ * 获取电子厂代码
+ *
+ * @return 电子厂代码
+ */
+ public String getFactoryCode() {
+ return this.factoryCode;
+ }
+
+ /**
+ * 设置电子厂代码
+ *
+ * @param factoryCode 电子厂代码
+ */
+ public void setFactoryCode(String factoryCode) {
+ this.factoryCode = factoryCode;
+ }
+
+ /**
+ * 获取鱼缸场代码
+ *
+ * @return 鱼缸场代码
+ */
+ public String getBrandCode() {
+ return this.brandCode;
+ }
+
+ /**
+ * 设置鱼缸场代码
+ *
+ * @param brandCode 鱼缸场代码
+ */
+ public void setBrandCode(String brandCode) {
+ this.brandCode = brandCode;
+ }
+}
diff --git a/src/main/java/com/ifish/bean/Tbl_Device_User.java b/src/main/java/com/ifish/bean/Tbl_Device_User.java
new file mode 100644
index 0000000..08184a0
--- /dev/null
+++ b/src/main/java/com/ifish/bean/Tbl_Device_User.java
@@ -0,0 +1,293 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.bean;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * 设备与用户关系表(tbl_device_user)
+ *
+ * @author bianj
+ * @version 1.0.0 2017-06-27
+ */
+@Entity
+@Table(name = "tbl_device_user")
+public class Tbl_Device_User implements java.io.Serializable {
+
+ /**
+ * 版本号
+ */
+ private static final long serialVersionUID = -4018159739383033383L;
+
+ /**
+ * id
+ */
+ @Id
+ @Column(name = "id", unique = true, nullable = false, length = 10)
+ private Integer id;
+
+ /**
+ * 用户Id
+ */
+ @Column(name = "user_id", unique = true, nullable = false, length = 10)
+ private Integer userId;
+
+ /**
+ * 设备Id
+ */
+ @Column(name = "device_id", unique = true, nullable = false, length = 10)
+ private Integer deviceId;
+
+ /**
+ * 是否主控:1、主控制权,0、被分享者
+ */
+ @Column(name = "is_master", nullable = true, length = 1)
+ private String isMaster;
+
+ /**
+ * 显示名称
+ */
+ @Column(name = "show_name", nullable = true, length = 50)
+ private String showName;
+
+ /**
+ * 创建时间
+ */
+ @Column(name = "create_time", nullable = true)
+ private Date createTime;
+
+ /**
+ * 修改时间
+ */
+ @Column(name = "update_time", nullable = true)
+ private Date updateTime;
+
+ /**
+ * 保存的显示图标
+ */
+ @Column(name = "custom_icon_name", nullable = true, length = 100)
+ private String customIconName;
+
+ /**
+ * 保存的显示名称
+ */
+ @Column(name = "custom_show_name", nullable = true, length = 100)
+ private String customShowName;
+
+ /**
+ * 是否看护
+ */
+ @Column(name = "is_look", nullable = true, length = 1)
+ private String isLook;
+
+ /**
+ * 是否直播
+ */
+ @Column(name = "is_live", nullable = true, length = 1)
+ private String isLive;
+
+ /**
+ * 获取id
+ *
+ * @return id
+ */
+ public Integer getId() {
+ return this.id;
+ }
+
+ /**
+ * 设置id
+ *
+ * @param id id
+ */
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ /**
+ * 获取用户Id
+ *
+ * @return 用户Id
+ */
+ public Integer getUserId() {
+ return this.userId;
+ }
+
+ /**
+ * 设置用户Id
+ *
+ * @param userId 用户Id
+ */
+ public void setUserId(Integer userId) {
+ this.userId = userId;
+ }
+
+ /**
+ * 获取设备Id
+ *
+ * @return 设备Id
+ */
+ public Integer getDeviceId() {
+ return this.deviceId;
+ }
+
+ /**
+ * 设置设备Id
+ *
+ * @param deviceId 设备Id
+ */
+ public void setDeviceId(Integer deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ /**
+ * 获取是否主控:1、主控制权,0、被分享者
+ *
+ * @return 是否主控:1、主控制权
+ */
+ public String getIsMaster() {
+ return this.isMaster;
+ }
+
+ /**
+ * 设置是否主控:1、主控制权,0、被分享者
+ *
+ * @param isMaster 是否主控:1、主控制权,0、被分享者
+ */
+ public void setIsMaster(String isMaster) {
+ this.isMaster = isMaster;
+ }
+
+ /**
+ * 获取显示名称
+ *
+ * @return 显示名称
+ */
+ public String getShowName() {
+ return this.showName;
+ }
+
+ /**
+ * 设置显示名称
+ *
+ * @param showName 显示名称
+ */
+ public void setShowName(String showName) {
+ this.showName = showName;
+ }
+
+ /**
+ * 获取创建时间
+ *
+ * @return 创建时间
+ */
+ public Date getCreateTime() {
+ return this.createTime;
+ }
+
+ /**
+ * 设置创建时间
+ *
+ * @param createTime 创建时间
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ /**
+ * 获取修改时间
+ *
+ * @return 修改时间
+ */
+ public Date getUpdateTime() {
+ return this.updateTime;
+ }
+
+ /**
+ * 设置修改时间
+ *
+ * @param updateTime 修改时间
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+
+ /**
+ * 获取保存的显示图标
+ *
+ * @return 保存的显示图标
+ */
+ public String getCustomIconName() {
+ return this.customIconName;
+ }
+
+ /**
+ * 设置保存的显示图标
+ *
+ * @param customIconName 保存的显示图标
+ */
+ public void setCustomIconName(String customIconName) {
+ this.customIconName = customIconName;
+ }
+
+ /**
+ * 获取保存的显示名称
+ *
+ * @return 保存的显示名称
+ */
+ public String getCustomShowName() {
+ return this.customShowName;
+ }
+
+ /**
+ * 设置保存的显示名称
+ *
+ * @param customShowName 保存的显示名称
+ */
+ public void setCustomShowName(String customShowName) {
+ this.customShowName = customShowName;
+ }
+
+ /**
+ * 获取是否看护
+ *
+ * @return 是否看护
+ */
+ public String getIsLook() {
+ return this.isLook;
+ }
+
+ /**
+ * 设置是否看护
+ *
+ * @param isLook 是否看护
+ */
+ public void setIsLook(String isLook) {
+ this.isLook = isLook;
+ }
+
+ /**
+ * 获取是否直播
+ *
+ * @return 是否直播
+ */
+ public String getIsLive() {
+ return this.isLive;
+ }
+
+ /**
+ * 设置是否直播
+ *
+ * @param isLive 是否直播
+ */
+ public void setIsLive(String isLive) {
+ this.isLive = isLive;
+ }
+}
diff --git a/src/main/java/com/ifish/bean/Tbl_Factory_List.java b/src/main/java/com/ifish/bean/Tbl_Factory_List.java
new file mode 100644
index 0000000..b03bf10
--- /dev/null
+++ b/src/main/java/com/ifish/bean/Tbl_Factory_List.java
@@ -0,0 +1,125 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.bean;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * 电子厂详情表(tbl_factory_list)
+ *
+ * @author bianj
+ * @version 1.0.0 2017-07-03
+ */
+@Entity
+@Table(name = "tbl_factory_list")
+public class Tbl_Factory_List implements java.io.Serializable {
+
+ /**
+ * 版本号
+ */
+ private static final long serialVersionUID = -8290320819344778436L;
+
+ /**
+ * 电子厂代码
+ */
+ @Id
+ @Column(name = "factory_code", unique = true, nullable = false, length = 20)
+ private String factoryCode;
+
+ /**
+ * 电子厂名称
+ */
+ @Column(name = "factory_name", nullable = false, length = 20)
+ private String factoryName;
+
+ /**
+ * 创建时间
+ */
+ @Column(name = "create_time", nullable = true)
+ private Date createTime;
+
+ /**
+ * 是否收税:1收、0不收
+ */
+ @Column(name = "is_tax", nullable = true, length = 1)
+ private String isTax;
+
+ /**
+ * 获取电子厂代码
+ *
+ * @return 电子厂代码
+ */
+ public String getFactoryCode() {
+ return this.factoryCode;
+ }
+
+ /**
+ * 设置电子厂代码
+ *
+ * @param factoryCode 电子厂代码
+ */
+ public void setFactoryCode(String factoryCode) {
+ this.factoryCode = factoryCode;
+ }
+
+ /**
+ * 获取电子厂名称
+ *
+ * @return 电子厂名称
+ */
+ public String getFactoryName() {
+ return this.factoryName;
+ }
+
+ /**
+ * 设置电子厂名称
+ *
+ * @param factoryName 电子厂名称
+ */
+ public void setFactoryName(String factoryName) {
+ this.factoryName = factoryName;
+ }
+
+ /**
+ * 获取创建时间
+ *
+ * @return 创建时间
+ */
+ public Date getCreateTime() {
+ return this.createTime;
+ }
+
+ /**
+ * 设置创建时间
+ *
+ * @param createTime 创建时间
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ /**
+ * 获取是否收税:1收、0不收
+ *
+ * @return 是否收税
+ */
+ public String getIsTax() {
+ return this.isTax;
+ }
+
+ /**
+ * 设置是否收税:1收、0不收
+ *
+ * @param isTax 是否收税:1收、0不收
+ */
+ public void setIsTax(String isTax) {
+ this.isTax = isTax;
+ }
+}
diff --git a/src/main/java/com/ifish/bean/Tbl_HardWare_Type.java b/src/main/java/com/ifish/bean/Tbl_HardWare_Type.java
new file mode 100644
index 0000000..7760168
--- /dev/null
+++ b/src/main/java/com/ifish/bean/Tbl_HardWare_Type.java
@@ -0,0 +1,437 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.bean;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * 设备类型详情表(tbl_hardware_type)
+ *
+ * @author bianj
+ * @version 1.0.0 2017-06-27
+ */
+@Entity
+@Table(name = "tbl_hardware_type")
+public class Tbl_HardWare_Type implements java.io.Serializable {
+
+ /**
+ * 版本号
+ */
+ private static final long serialVersionUID = 7870932947017585134L;
+
+ /**
+ * 设备型号代码
+ */
+ @Id
+ @Column(name = "hardware_type", unique = true, nullable = false, length = 10)
+ private String hardwareType;
+
+ /**
+ * 电子厂代码
+ */
+ @Column(name = "factory_code", nullable = true, length = 20)
+ private String factoryCode;
+
+ /**
+ * 设备名称
+ */
+ @Column(name = "hardware_name", nullable = false, length = 20)
+ private String hardwareName;
+
+ /**
+ * 描述
+ */
+ @Column(name = "hardware_desc", nullable = true, length = 100)
+ private String hardwareDesc;
+
+ /**
+ * 创建时间
+ */
+ @Column(name = "create_time", nullable = true)
+ private Date createTime;
+
+ /**
+ * 控制个数
+ */
+ @Column(name = "control_amount", nullable = true, length = 10)
+ private Integer controlAmount;
+
+ /**
+ * 定时器个数
+ */
+ @Column(name = "timer_amount", nullable = true, length = 10)
+ private Integer timerAmount;
+
+ /**
+ * 是否自定义图标:1是、0否
+ */
+ @Column(name = "is_custom_icon", nullable = true, length = 1)
+ private String isCustomIcon;
+
+ /**
+ * 自定义图标根地址
+ */
+ @Column(name = "icon_link", nullable = true, length = 200)
+ private String iconLink;
+
+ /**
+ * 根地址下图标名称
+ */
+ @Column(name = "all_icon_name", nullable = true, length = 200)
+ private String allIconName;
+
+ /**
+ * 修改时间
+ */
+ @Column(name = "update_time", nullable = true)
+ private Date updateTime;
+
+ /**
+ * 是否有背光:1是、0否
+ */
+ @Column(name = "is_lightness", nullable = true, length = 1)
+ private String isLightness;
+
+ /**
+ * 是否有柜灯:1是、0否
+ */
+ @Column(name = "is_sark_lamp", nullable = true, length = 1)
+ private String isSarkLamp;
+
+ /**
+ * 是否有工作模式:1是、0否
+ */
+ @Column(name = "is_work_model", nullable = true, length = 1)
+ private String isWorkModel;
+
+ /**
+ * 显示名称
+ */
+ @Column(name = "all_show_name", nullable = true, length = 200)
+ private String allShowName;
+
+ /**
+ * 默认名称
+ */
+ @Column(name = "default_show_name", nullable = true, length = 200)
+ private String defaultShowName;
+
+ /**
+ * 默认图标
+ */
+ @Column(name = "default_icon_name", nullable = true, length = 200)
+ private String defaultIconName;
+
+ /**
+ * 获取设备型号代码
+ *
+ * @return 设备型号代码
+ */
+ public String getHardwareType() {
+ return this.hardwareType;
+ }
+
+ /**
+ * 设置设备型号代码
+ *
+ * @param hardwareType 设备型号代码
+ */
+ public void setHardwareType(String hardwareType) {
+ this.hardwareType = hardwareType;
+ }
+
+ /**
+ * 获取电子厂代码
+ *
+ * @return 电子厂代码
+ */
+ public String getFactoryCode() {
+ return this.factoryCode;
+ }
+
+ /**
+ * 设置电子厂代码
+ *
+ * @param factoryCode 电子厂代码
+ */
+ public void setFactoryCode(String factoryCode) {
+ this.factoryCode = factoryCode;
+ }
+
+ /**
+ * 获取设备名称
+ *
+ * @return 设备名称
+ */
+ public String getHardwareName() {
+ return this.hardwareName;
+ }
+
+ /**
+ * 设置设备名称
+ *
+ * @param hardwareName 设备名称
+ */
+ public void setHardwareName(String hardwareName) {
+ this.hardwareName = hardwareName;
+ }
+
+ /**
+ * 获取描述
+ *
+ * @return 描述
+ */
+ public String getHardwareDesc() {
+ return this.hardwareDesc;
+ }
+
+ /**
+ * 设置描述
+ *
+ * @param hardwareDesc 描述
+ */
+ public void setHardwareDesc(String hardwareDesc) {
+ this.hardwareDesc = hardwareDesc;
+ }
+
+ /**
+ * 获取创建时间
+ *
+ * @return 创建时间
+ */
+ public Date getCreateTime() {
+ return this.createTime;
+ }
+
+ /**
+ * 设置创建时间
+ *
+ * @param createTime 创建时间
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ /**
+ * 获取控制个数
+ *
+ * @return 控制个数
+ */
+ public Integer getControlAmount() {
+ return this.controlAmount;
+ }
+
+ /**
+ * 设置控制个数
+ *
+ * @param controlAmount 控制个数
+ */
+ public void setControlAmount(Integer controlAmount) {
+ this.controlAmount = controlAmount;
+ }
+
+ /**
+ * 获取定时器个数
+ *
+ * @return 定时器个数
+ */
+ public Integer getTimerAmount() {
+ return this.timerAmount;
+ }
+
+ /**
+ * 设置定时器个数
+ *
+ * @param timerAmount 定时器个数
+ */
+ public void setTimerAmount(Integer timerAmount) {
+ this.timerAmount = timerAmount;
+ }
+
+ /**
+ * 获取是否自定义图标:1是、0否
+ *
+ * @return 是否自定义图标
+ */
+ public String getIsCustomIcon() {
+ return this.isCustomIcon;
+ }
+
+ /**
+ * 设置是否自定义图标:1是、0否
+ *
+ * @param isCustomIcon 是否自定义图标:1是、0否
+ */
+ public void setIsCustomIcon(String isCustomIcon) {
+ this.isCustomIcon = isCustomIcon;
+ }
+
+ /**
+ * 获取自定义图标根地址
+ *
+ * @return 自定义图标根地址
+ */
+ public String getIconLink() {
+ return this.iconLink;
+ }
+
+ /**
+ * 设置自定义图标根地址
+ *
+ * @param iconLink 自定义图标根地址
+ */
+ public void setIconLink(String iconLink) {
+ this.iconLink = iconLink;
+ }
+
+ /**
+ * 获取根地址下图标名称
+ *
+ * @return 根地址下图标名称
+ */
+ public String getAllIconName() {
+ return this.allIconName;
+ }
+
+ /**
+ * 设置根地址下图标名称
+ *
+ * @param allIconName 根地址下图标名称
+ */
+ public void setAllIconName(String allIconName) {
+ this.allIconName = allIconName;
+ }
+
+ /**
+ * 获取修改时间
+ *
+ * @return 修改时间
+ */
+ public Date getUpdateTime() {
+ return this.updateTime;
+ }
+
+ /**
+ * 设置修改时间
+ *
+ * @param updateTime 修改时间
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+
+ /**
+ * 获取是否有背光:1是、0否
+ *
+ * @return 是否有背光
+ */
+ public String getIsLightness() {
+ return this.isLightness;
+ }
+
+ /**
+ * 设置是否有背光:1是、0否
+ *
+ * @param isLightness 是否有背光:1是、0否
+ */
+ public void setIsLightness(String isLightness) {
+ this.isLightness = isLightness;
+ }
+
+ /**
+ * 获取是否有柜灯:1是、0否
+ *
+ * @return 是否有柜灯
+ */
+ public String getIsSarkLamp() {
+ return this.isSarkLamp;
+ }
+
+ /**
+ * 设置是否有柜灯:1是、0否
+ *
+ * @param isSarkLamp 是否有柜灯:1是、0否
+ */
+ public void setIsSarkLamp(String isSarkLamp) {
+ this.isSarkLamp = isSarkLamp;
+ }
+
+ /**
+ * 获取是否有工作模式:1是、0否
+ *
+ * @return 是否有工作模式
+ */
+ public String getIsWorkModel() {
+ return this.isWorkModel;
+ }
+
+ /**
+ * 设置是否有工作模式:1是、0否
+ *
+ * @param isWorkModel 是否有工作模式:1是、0否
+ */
+ public void setIsWorkModel(String isWorkModel) {
+ this.isWorkModel = isWorkModel;
+ }
+
+ /**
+ * 获取显示名称
+ *
+ * @return 显示名称
+ */
+ public String getAllShowName() {
+ return this.allShowName;
+ }
+
+ /**
+ * 设置显示名称
+ *
+ * @param allShowName 显示名称
+ */
+ public void setAllShowName(String allShowName) {
+ this.allShowName = allShowName;
+ }
+
+ /**
+ * 获取默认名称
+ *
+ * @return 默认名称
+ */
+ public String getDefaultShowName() {
+ return this.defaultShowName;
+ }
+
+ /**
+ * 设置默认名称
+ *
+ * @param defaultShowName 默认名称
+ */
+ public void setDefaultShowName(String defaultShowName) {
+ this.defaultShowName = defaultShowName;
+ }
+
+ /**
+ * 获取默认图标
+ *
+ * @return 默认图标
+ */
+ public String getDefaultIconName() {
+ return this.defaultIconName;
+ }
+
+ /**
+ * 设置默认图标
+ *
+ * @param defaultIconName 默认图标
+ */
+ public void setDefaultIconName(String defaultIconName) {
+ this.defaultIconName = defaultIconName;
+ }
+}
diff --git a/src/main/java/com/ifish/bean/Tbl_Push_List.java b/src/main/java/com/ifish/bean/Tbl_Push_List.java
new file mode 100644
index 0000000..8bfa849
--- /dev/null
+++ b/src/main/java/com/ifish/bean/Tbl_Push_List.java
@@ -0,0 +1,465 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.bean;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * 推送详情表(tbl_push_list)
+ *
+ * @author bianj
+ * @version 1.0.0 2017-07-03
+ */
+@Entity
+@Table(name = "tbl_push_list")
+public class Tbl_Push_List implements java.io.Serializable {
+
+ /**
+ * 版本号
+ */
+ private static final long serialVersionUID = -7760764975977010045L;
+
+ /**
+ * ID
+ */
+ @Id
+ @Column(name = "push_id", unique = true, nullable = false, length = 10)
+ private Integer pushId;
+
+ /**
+ * 用户Id
+ */
+ @Column(name = "user_id", nullable = true, length = 10)
+ private Integer userId;
+
+ /**
+ * 设备Id
+ */
+ @Column(name = "device_id", nullable = true, length = 10)
+ private Integer deviceId;
+
+ /**
+ * 显示名称
+ */
+ @Column(name = "show_name", nullable = true, length = 20)
+ private String showName;
+
+ /**
+ * 推送手机类型
+ */
+ @Column(name = "phone_type", nullable = true, length = 20)
+ private String phoneType;
+
+ /**
+ * 推送消息类型
+ * 1."remove_device","解绑通知";2."wendu_warn","温度预警;3."qu_reply","问题反馈";4."app_update","IOS更新推送";5."remind_water","换水提醒";6."offline_push","离线通知";7."send_report","看护报告";8."shops_push","看护通知";9."all_push","所有用户推送"
+ */
+ @Column(name = "push_type", nullable = true, length = 20)
+ private String pushType;
+
+ /**
+ * 推送标题
+ */
+ @Column(name = "push_title", nullable = true, length = 100)
+ private String pushTitle;
+
+ /**
+ * 推送内容
+ */
+ @Column(name = "push_context", nullable = true, length = 200)
+ private String pushContext;
+
+ /**
+ * 创建时间
+ */
+ @Column(name = "create_time", nullable = true)
+ private Date createTime;
+
+ /**
+ * 链接
+ */
+ @Column(name = "push_link", nullable = false, length = 100)
+ private String pushLink;
+
+ /**
+ * 极光推送状态
+ */
+ @Column(name = "jpush_status", nullable = true, length = 1)
+ private String jpushStatus;
+
+ /**
+ * 谷歌推送状态
+ */
+ @Column(name = "google_status", nullable = true, length = 1)
+ private String googleStatus;
+
+ /**
+ * 看护报告Id
+ */
+ @Column(name = "report_id", nullable = true, length = 10)
+ private Integer reportId;
+
+ /**
+ * MCU启动次数
+ */
+ @Column(name = "mcu_count", nullable = true, length = 10)
+ private Integer mcuCount;
+
+ /**
+ * 模块启动次数
+ */
+ @Column(name = "modular_count", nullable = true, length = 10)
+ private Integer modularCount;
+
+ /**
+ * 连接路由器次数
+ */
+ @Column(name = "router_count", nullable = true, length = 10)
+ private Integer routerCount;
+
+ /**
+ * 成功连接服务器次数
+ */
+ @Column(name = "server_count", nullable = true, length = 10)
+ private Integer serverCount;
+
+ /**
+ * 尝试连接服务器次数
+ */
+ @Column(name = "server_try_count", nullable = true, length = 10)
+ private Integer serverTryCount;
+
+ /**
+ * 获取ID
+ *
+ * @return ID
+ */
+ public Integer getPushId() {
+ return this.pushId;
+ }
+
+ /**
+ * 设置ID
+ *
+ * @param pushId ID
+ */
+ public void setPushId(Integer pushId) {
+ this.pushId = pushId;
+ }
+
+ /**
+ * 获取用户Id
+ *
+ * @return 用户Id
+ */
+ public Integer getUserId() {
+ return this.userId;
+ }
+
+ /**
+ * 设置用户Id
+ *
+ * @param userId 用户Id
+ */
+ public void setUserId(Integer userId) {
+ this.userId = userId;
+ }
+
+ /**
+ * 获取设备Id
+ *
+ * @return 设备Id
+ */
+ public Integer getDeviceId() {
+ return this.deviceId;
+ }
+
+ /**
+ * 设置设备Id
+ *
+ * @param deviceId 设备Id
+ */
+ public void setDeviceId(Integer deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ /**
+ * 获取显示名称
+ *
+ * @return 显示名称
+ */
+ public String getShowName() {
+ return this.showName;
+ }
+
+ /**
+ * 设置显示名称
+ *
+ * @param showName 显示名称
+ */
+ public void setShowName(String showName) {
+ this.showName = showName;
+ }
+
+ /**
+ * 获取推送手机类型
+ *
+ * @return 推送手机类型
+ */
+ public String getPhoneType() {
+ return this.phoneType;
+ }
+
+ /**
+ * 设置推送手机类型
+ *
+ * @param phoneType 推送手机类型
+ */
+ public void setPhoneType(String phoneType) {
+ this.phoneType = phoneType;
+ }
+
+ /**
+ * 获取推送消息类型
+ * 1."remove_device","解绑通知";2."wendu_warn","温度预警;3."qu_reply","问题反馈";4."app_update","IOS更新推送";5."remind_water","换水提醒";6."offline_push","离线通知";7."send_report","看护报告";8."shops_push","看护通知";9."all_push","所有用户推送"
+ *
+ * @return 推送消息类型 1."remove_device"
+ */
+ public String getPushType() {
+ return this.pushType;
+ }
+
+ /**
+ * 设置推送消息类型
+ * 1."remove_device","解绑通知";2."wendu_warn","温度预警;3."qu_reply","问题反馈";4."app_update","IOS更新推送";5."remind_water","换水提醒";6."offline_push","离线通知";7."send_report","看护报告";8."shops_push","看护通知";9."all_push","所有用户推送"
+ *
+ * @param pushType 推送消息类型
+ * 1."remove_device","解绑通知";2."wendu_warn","温度预警;3."qu_reply","问题反馈";4."app_update","IOS更新推送";5."remind_water","换水提醒";6."offline_push","离线通知";7."send_report","看护报告";8."shops_push","看护通知";9."all_push","所有用户推送"
+ */
+ public void setPushType(String pushType) {
+ this.pushType = pushType;
+ }
+
+ /**
+ * 获取推送标题
+ *
+ * @return 推送标题
+ */
+ public String getPushTitle() {
+ return this.pushTitle;
+ }
+
+ /**
+ * 设置推送标题
+ *
+ * @param pushTitle 推送标题
+ */
+ public void setPushTitle(String pushTitle) {
+ this.pushTitle = pushTitle;
+ }
+
+ /**
+ * 获取推送内容
+ *
+ * @return 推送内容
+ */
+ public String getPushContext() {
+ return this.pushContext;
+ }
+
+ /**
+ * 设置推送内容
+ *
+ * @param pushContext 推送内容
+ */
+ public void setPushContext(String pushContext) {
+ this.pushContext = pushContext;
+ }
+
+ /**
+ * 获取创建时间
+ *
+ * @return 创建时间
+ */
+ public Date getCreateTime() {
+ return this.createTime;
+ }
+
+ /**
+ * 设置创建时间
+ *
+ * @param createTime 创建时间
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ /**
+ * 获取链接
+ *
+ * @return 链接
+ */
+ public String getPushLink() {
+ return this.pushLink;
+ }
+
+ /**
+ * 设置链接
+ *
+ * @param pushLink 链接
+ */
+ public void setPushLink(String pushLink) {
+ this.pushLink = pushLink;
+ }
+
+ /**
+ * 获取极光推送状态
+ *
+ * @return 极光推送状态
+ */
+ public String getJpushStatus() {
+ return this.jpushStatus;
+ }
+
+ /**
+ * 设置极光推送状态
+ *
+ * @param jpushStatus 极光推送状态
+ */
+ public void setJpushStatus(String jpushStatus) {
+ this.jpushStatus = jpushStatus;
+ }
+
+ /**
+ * 获取谷歌推送状态
+ *
+ * @return 谷歌推送状态
+ */
+ public String getGoogleStatus() {
+ return this.googleStatus;
+ }
+
+ /**
+ * 设置谷歌推送状态
+ *
+ * @param googleStatus 谷歌推送状态
+ */
+ public void setGoogleStatus(String googleStatus) {
+ this.googleStatus = googleStatus;
+ }
+
+ /**
+ * 获取看护报告Id
+ *
+ * @return 看护报告Id
+ */
+ public Integer getReportId() {
+ return this.reportId;
+ }
+
+ /**
+ * 设置看护报告Id
+ *
+ * @param reportId 看护报告Id
+ */
+ public void setReportId(Integer reportId) {
+ this.reportId = reportId;
+ }
+
+ /**
+ * 获取MCU启动次数
+ *
+ * @return MCU启动次数
+ */
+ public Integer getMcuCount() {
+ return this.mcuCount;
+ }
+
+ /**
+ * 设置MCU启动次数
+ *
+ * @param mcuCount MCU启动次数
+ */
+ public void setMcuCount(Integer mcuCount) {
+ this.mcuCount = mcuCount;
+ }
+
+ /**
+ * 获取模块启动次数
+ *
+ * @return 模块启动次数
+ */
+ public Integer getModularCount() {
+ return this.modularCount;
+ }
+
+ /**
+ * 设置模块启动次数
+ *
+ * @param modularCount 模块启动次数
+ */
+ public void setModularCount(Integer modularCount) {
+ this.modularCount = modularCount;
+ }
+
+ /**
+ * 获取连接路由器次数
+ *
+ * @return 连接路由器次数
+ */
+ public Integer getRouterCount() {
+ return this.routerCount;
+ }
+
+ /**
+ * 设置连接路由器次数
+ *
+ * @param routerCount 连接路由器次数
+ */
+ public void setRouterCount(Integer routerCount) {
+ this.routerCount = routerCount;
+ }
+
+ /**
+ * 获取成功连接服务器次数
+ *
+ * @return 成功连接服务器次数
+ */
+ public Integer getServerCount() {
+ return this.serverCount;
+ }
+
+ /**
+ * 设置成功连接服务器次数
+ *
+ * @param serverCount 成功连接服务器次数
+ */
+ public void setServerCount(Integer serverCount) {
+ this.serverCount = serverCount;
+ }
+
+ /**
+ * 获取尝试连接服务器次数
+ *
+ * @return 尝试连接服务器次数
+ */
+ public Integer getServerTryCount() {
+ return this.serverTryCount;
+ }
+
+ /**
+ * 设置尝试连接服务器次数
+ *
+ * @param serverTryCount 尝试连接服务器次数
+ */
+ public void setServerTryCount(Integer serverTryCount) {
+ this.serverTryCount = serverTryCount;
+ }
+}
diff --git a/src/main/java/com/ifish/bean/Tbl_User.java b/src/main/java/com/ifish/bean/Tbl_User.java
new file mode 100644
index 0000000..57cb9af
--- /dev/null
+++ b/src/main/java/com/ifish/bean/Tbl_User.java
@@ -0,0 +1,557 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.bean;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * 用户详情表(tbl_user)
+ *
+ * @author bianj
+ * @version 1.0.0 2017-06-28
+ */
+@Entity
+@Table(name = "tbl_user")
+public class Tbl_User implements java.io.Serializable {
+
+ /**
+ * 版本号
+ */
+ private static final long serialVersionUID = -3293426131332327827L;
+
+ /**
+ * 用户Id
+ */
+ @Id
+ @Column(name = "user_id", unique = true, nullable = false, length = 10)
+ private Integer userId;
+
+ /**
+ * 昵称
+ */
+ @Column(name = "nick_name", nullable = true, length = 20)
+ private String nickName;
+
+ /**
+ * 密码
+ */
+ @Column(name = "user_password", nullable = true, length = 32)
+ private String userPassword;
+
+ /**
+ * 手机
+ */
+ @Column(name = "phone_number", unique = true, nullable = true, length = 11)
+ private String phoneNumber;
+
+ /**
+ * 邮箱
+ */
+ @Column(name = "user_email", unique = true, nullable = true, length = 50)
+ private String userEmail;
+
+ /**
+ * 用户类型
+ */
+ @Column(name = "user_type", nullable = false, length = 1)
+ private String userType;
+
+ /**
+ * 头像
+ */
+ @Column(name = "user_img", nullable = true, length = 100)
+ private String userImg;
+
+ /**
+ * 性别
+ */
+ @Column(name = "user_sex", nullable = true, length = 1)
+ private String userSex;
+
+ /**
+ * 登陆次数
+ */
+ @Column(name = "login_count", nullable = true, length = 10)
+ private Integer loginCount;
+
+ /**
+ * 修改时间
+ */
+ @Column(name = "update_time", nullable = true)
+ private Date updateTime;
+
+ /**
+ * 登陆时间
+ */
+ @Column(name = "login_time", nullable = true)
+ private Date loginTime;
+
+ /**
+ * 注册时间
+ */
+ @Column(name = "create_time", nullable = true)
+ private Date createTime;
+
+ /**
+ * 登陆手机类型
+ */
+ @Column(name = "login_type", nullable = true, length = 10)
+ private String loginType;
+
+ /**
+ * 备注
+ */
+ @Column(name = "remarks", nullable = true, length = 100)
+ private String remarks;
+
+ /**
+ * 地址
+ */
+ @Column(name = "address", nullable = true, length = 200)
+ private String address;
+
+ /**
+ * 技威Code1
+ */
+ @Column(name = "p2pverify_code1", nullable = true, length = 50)
+ private String p2pverifyCode1;
+
+ /**
+ * 技威Code2
+ */
+ @Column(name = "p2pverify_code2", nullable = true, length = 50)
+ private String p2pverifyCode2;
+
+ /**
+ * 技威用户ID
+ */
+ @Column(name = "gwell_userid", nullable = true, length = 50)
+ private String gwellUserid;
+
+ /**
+ * 是否注册技威:1已注册、0未注册
+ */
+ @Column(name = "is_register_gwell", nullable = true, length = 1)
+ private String isRegisterGwell;
+
+ /**
+ * 极光用户ID
+ */
+ @Column(name = "jiguang_userid", nullable = true, length = 50)
+ private String jiguangUserid;
+
+ /**
+ * 经度
+ */
+ @Column(name = "longitude", nullable = true)
+ private Double longitude;
+
+ /**
+ * 纬度
+ */
+ @Column(name = "latitude", nullable = true)
+ private Double latitude;
+
+ /**
+ * 获取用户Id
+ *
+ * @return 用户Id
+ */
+ public Integer getUserId() {
+ return this.userId;
+ }
+
+ /**
+ * 设置用户Id
+ *
+ * @param userId 用户Id
+ */
+ public void setUserId(Integer userId) {
+ this.userId = userId;
+ }
+
+ /**
+ * 获取昵称
+ *
+ * @return 昵称
+ */
+ public String getNickName() {
+ return this.nickName;
+ }
+
+ /**
+ * 设置昵称
+ *
+ * @param nickName 昵称
+ */
+ public void setNickName(String nickName) {
+ this.nickName = nickName;
+ }
+
+ /**
+ * 获取密码
+ *
+ * @return 密码
+ */
+ public String getUserPassword() {
+ return this.userPassword;
+ }
+
+ /**
+ * 设置密码
+ *
+ * @param userPassword 密码
+ */
+ public void setUserPassword(String userPassword) {
+ this.userPassword = userPassword;
+ }
+
+ /**
+ * 获取手机
+ *
+ * @return 手机
+ */
+ public String getPhoneNumber() {
+ return this.phoneNumber;
+ }
+
+ /**
+ * 设置手机
+ *
+ * @param phoneNumber 手机
+ */
+ public void setPhoneNumber(String phoneNumber) {
+ this.phoneNumber = phoneNumber;
+ }
+
+ /**
+ * 获取邮箱
+ *
+ * @return 邮箱
+ */
+ public String getUserEmail() {
+ return this.userEmail;
+ }
+
+ /**
+ * 设置邮箱
+ *
+ * @param userEmail 邮箱
+ */
+ public void setUserEmail(String userEmail) {
+ this.userEmail = userEmail;
+ }
+
+ /**
+ * 获取用户类型
+ *
+ * @return 用户类型
+ */
+ public String getUserType() {
+ return this.userType;
+ }
+
+ /**
+ * 设置用户类型
+ *
+ * @param userType 用户类型
+ */
+ public void setUserType(String userType) {
+ this.userType = userType;
+ }
+
+ /**
+ * 获取头像
+ *
+ * @return 头像
+ */
+ public String getUserImg() {
+ return this.userImg;
+ }
+
+ /**
+ * 设置头像
+ *
+ * @param userImg 头像
+ */
+ public void setUserImg(String userImg) {
+ this.userImg = userImg;
+ }
+
+ /**
+ * 获取性别
+ *
+ * @return 性别
+ */
+ public String getUserSex() {
+ return this.userSex;
+ }
+
+ /**
+ * 设置性别
+ *
+ * @param userSex 性别
+ */
+ public void setUserSex(String userSex) {
+ this.userSex = userSex;
+ }
+
+ /**
+ * 获取登陆次数
+ *
+ * @return 登陆次数
+ */
+ public Integer getLoginCount() {
+ return this.loginCount;
+ }
+
+ /**
+ * 设置登陆次数
+ *
+ * @param loginCount 登陆次数
+ */
+ public void setLoginCount(Integer loginCount) {
+ this.loginCount = loginCount;
+ }
+
+ /**
+ * 获取修改时间
+ *
+ * @return 修改时间
+ */
+ public Date getUpdateTime() {
+ return this.updateTime;
+ }
+
+ /**
+ * 设置修改时间
+ *
+ * @param updateTime 修改时间
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+
+ /**
+ * 获取登陆时间
+ *
+ * @return 登陆时间
+ */
+ public Date getLoginTime() {
+ return this.loginTime;
+ }
+
+ /**
+ * 设置登陆时间
+ *
+ * @param loginTime 登陆时间
+ */
+ public void setLoginTime(Date loginTime) {
+ this.loginTime = loginTime;
+ }
+
+ /**
+ * 获取注册时间
+ *
+ * @return 注册时间
+ */
+ public Date getCreateTime() {
+ return this.createTime;
+ }
+
+ /**
+ * 设置注册时间
+ *
+ * @param createTime 注册时间
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ /**
+ * 获取登陆手机类型
+ *
+ * @return 登陆手机类型
+ */
+ public String getLoginType() {
+ return this.loginType;
+ }
+
+ /**
+ * 设置登陆手机类型
+ *
+ * @param loginType 登陆手机类型
+ */
+ public void setLoginType(String loginType) {
+ this.loginType = loginType;
+ }
+
+ /**
+ * 获取备注
+ *
+ * @return 备注
+ */
+ public String getRemarks() {
+ return this.remarks;
+ }
+
+ /**
+ * 设置备注
+ *
+ * @param remarks 备注
+ */
+ public void setRemarks(String remarks) {
+ this.remarks = remarks;
+ }
+
+ /**
+ * 获取地址
+ *
+ * @return 地址
+ */
+ public String getAddress() {
+ return this.address;
+ }
+
+ /**
+ * 设置地址
+ *
+ * @param address 地址
+ */
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ /**
+ * 获取技威Code1
+ *
+ * @return 技威Code1
+ */
+ public String getP2pverifyCode1() {
+ return this.p2pverifyCode1;
+ }
+
+ /**
+ * 设置技威Code1
+ *
+ * @param p2pverifyCode1 技威Code1
+ */
+ public void setP2pverifyCode1(String p2pverifyCode1) {
+ this.p2pverifyCode1 = p2pverifyCode1;
+ }
+
+ /**
+ * 获取技威Code2
+ *
+ * @return 技威Code2
+ */
+ public String getP2pverifyCode2() {
+ return this.p2pverifyCode2;
+ }
+
+ /**
+ * 设置技威Code2
+ *
+ * @param p2pverifyCode2 技威Code2
+ */
+ public void setP2pverifyCode2(String p2pverifyCode2) {
+ this.p2pverifyCode2 = p2pverifyCode2;
+ }
+
+ /**
+ * 获取技威用户ID
+ *
+ * @return 技威用户ID
+ */
+ public String getGwellUserid() {
+ return this.gwellUserid;
+ }
+
+ /**
+ * 设置技威用户ID
+ *
+ * @param gwellUserid 技威用户ID
+ */
+ public void setGwellUserid(String gwellUserid) {
+ this.gwellUserid = gwellUserid;
+ }
+
+ /**
+ * 获取是否注册技威:1已注册、0未注册
+ *
+ * @return 是否注册技威
+ */
+ public String getIsRegisterGwell() {
+ return this.isRegisterGwell;
+ }
+
+ /**
+ * 设置是否注册技威:1已注册、0未注册
+ *
+ * @param isRegisterGwell 是否注册技威:1已注册、0未注册
+ */
+ public void setIsRegisterGwell(String isRegisterGwell) {
+ this.isRegisterGwell = isRegisterGwell;
+ }
+
+ /**
+ * 获取极光用户ID
+ *
+ * @return 极光用户ID
+ */
+ public String getJiguangUserid() {
+ return this.jiguangUserid;
+ }
+
+ /**
+ * 设置极光用户ID
+ *
+ * @param jiguangUserid 极光用户ID
+ */
+ public void setJiguangUserid(String jiguangUserid) {
+ this.jiguangUserid = jiguangUserid;
+ }
+
+ /**
+ * 获取经度
+ *
+ * @return 经度
+ */
+ public Double getLongitude() {
+ return this.longitude;
+ }
+
+ /**
+ * 设置经度
+ *
+ * @param longitude 经度
+ */
+ public void setLongitude(Double longitude) {
+ this.longitude = longitude;
+ }
+
+ /**
+ * 获取纬度
+ *
+ * @return 纬度
+ */
+ public Double getLatitude() {
+ return this.latitude;
+ }
+
+ /**
+ * 设置纬度
+ *
+ * @param latitude 纬度
+ */
+ public void setLatitude(Double latitude) {
+ this.latitude = latitude;
+ }
+}
diff --git a/src/main/java/com/ifish/config/MinaConfig.java b/src/main/java/com/ifish/config/MinaConfig.java
new file mode 100644
index 0000000..00f9d5b
--- /dev/null
+++ b/src/main/java/com/ifish/config/MinaConfig.java
@@ -0,0 +1,139 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.config;
+
+import com.ifish.socket.codeFactory.ServerCodecFactory;
+import com.ifish.socket.config.JobFactory;
+import com.ifish.socket.config.MinaServerHandler;
+import com.ifish.socket.config.MyInetSocketAddress;
+import com.ifish.socket.config.ScheduleJob;
+import com.ifish.socket.config.SomeServer;
+import com.ifish.socket.webService.ServiceBean;
+import com.ifish.util.IfishFilePath;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.filter.logging.LoggingFilter;
+import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
+import org.springframework.context.annotation.Bean;
+
+/**
+ *
+ * @author Administrator
+ */
+public class MinaConfig {
+
+ /**
+ * webService
+ *
+ * @return
+ */
+ @Bean
+ public ServiceBean serviceBean() {
+ return new ServiceBean();
+ }
+
+ /**
+ * 消息处理类
+ *
+ * @return
+ */
+ @Bean
+ public SomeServer someServer() {
+ return new SomeServer();
+ }
+
+ /**
+ * 实现job中注入bean
+ *
+ * @return
+ */
+ @Bean
+ public JobFactory jobFactory() {
+ return new JobFactory();
+ }
+
+ /**
+ * 调度任务
+ *
+ * @return
+ */
+ @Bean
+ public ScheduleJob scheduleJob() {
+ return new ScheduleJob();
+ }
+
+ /**
+ * 自定义的serverHandler
+ *
+ * @return
+ */
+ @Bean
+ public MinaServerHandler serverHandler() {
+ return new MinaServerHandler();
+ }
+
+ /**
+ * 指定服务端地址和端口
+ *
+ * @return
+ */
+ @Bean
+ public MyInetSocketAddress address() {
+ MyInetSocketAddress myInetSocketAddress = new MyInetSocketAddress(IfishFilePath.ifiship, IfishFilePath.ifishport);
+ return myInetSocketAddress;
+ }
+
+ /**
+ * 编码filter
+ *
+ * @return
+ */
+ @Bean
+ public ProtocolCodecFilter codecFilter() {
+ return new ProtocolCodecFilter(new ServerCodecFactory());
+ }
+
+ /**
+ * 日志filter
+ *
+ * @return
+ */
+ @Bean
+ public LoggingFilter loggingFilter() {
+ return new LoggingFilter();
+ }
+
+ /**
+ * 过滤器链
+ *
+ * @return
+ */
+ @Bean
+ public DefaultIoFilterChainBuilder filterChainBuilder() {
+ DefaultIoFilterChainBuilder defaultIoFilterChainBuilder = new DefaultIoFilterChainBuilder();
+ Map map = new HashMap();
+ map.put("codecFilter", codecFilter());
+ defaultIoFilterChainBuilder.setFilters(map);
+ return defaultIoFilterChainBuilder;
+ }
+
+ /**
+ * 开始运行socket服务
+ * @return
+ */
+ @Bean(initMethod = "bind", destroyMethod = "unbind")
+ public NioSocketAcceptor ioAcceptor() {
+ NioSocketAcceptor nioSocketAcceptor = new NioSocketAcceptor();
+ nioSocketAcceptor.setHandler(serverHandler());
+ nioSocketAcceptor.setDefaultLocalAddress(address().getSocketAddress());
+ nioSocketAcceptor.setFilterChainBuilder(filterChainBuilder());
+ nioSocketAcceptor.setReuseAddress(true);
+ nioSocketAcceptor.getSessionConfig().setBothIdleTime(0);
+ return nioSocketAcceptor;
+ }
+}
diff --git a/src/main/java/com/ifish/config/MyWSServletContextListener.java b/src/main/java/com/ifish/config/MyWSServletContextListener.java
new file mode 100644
index 0000000..d2da971
--- /dev/null
+++ b/src/main/java/com/ifish/config/MyWSServletContextListener.java
@@ -0,0 +1,14 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.config;
+
+/**
+ *
+ * @author Administrator
+ */
+public class MyWSServletContextListener {
+
+}
diff --git a/src/main/java/com/ifish/config/MybatisConfig.java b/src/main/java/com/ifish/config/MybatisConfig.java
new file mode 100644
index 0000000..235479f
--- /dev/null
+++ b/src/main/java/com/ifish/config/MybatisConfig.java
@@ -0,0 +1,86 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.config;
+
+import javax.sql.DataSource;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.mapper.MapperScannerConfigurer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ *
+ * @author Administrator
+ */
+@Configuration
+@EnableTransactionManagement
+public class MybatisConfig {
+
+ @Bean
+ public DataSource dataSource() {
+// try {
+// ComboPooledDataSource datasourc = new ComboPooledDataSource();
+// datasourc.setDriverClass(JdbcProperties.driverClassName);
+// datasourc.setJdbcUrl(JdbcProperties.url);
+// datasourc.setUser(JdbcProperties.username);
+// datasourc.setPassword(JdbcProperties.password);
+// datasourc.setAutoCommitOnClose(JdbcProperties.autoCommitOnClose);
+// datasourc.setInitialPoolSize(JdbcProperties.initialPoolSize);
+// datasourc.setMinPoolSize(JdbcProperties.minPoolSize);
+// datasourc.setMaxPoolSize(JdbcProperties.maxPoolSize);
+// datasourc.setAcquireIncrement(JdbcProperties.acquireIncrement);
+// datasourc.setCheckoutTimeout(JdbcProperties.checkoutTimeout);
+// datasourc.setMaxIdleTime(JdbcProperties.maxIdleTime);
+// datasourc.setIdleConnectionTestPeriod(JdbcProperties.idleConnectionTestPeriod);
+// return datasourc;
+// } catch (Exception e) {
+//
+// }
+ DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName("com.mysql.jdbc.Driver");
+ //线上生产数据库连接
+ dataSource.setUsername("ifish");
+ dataSource.setPassword("ifish7pwd");
+ dataSource.setUrl("jdbc:mysql://localhost:3306/myfishdbenglish?characterEncoding=UTF-8");
+ return dataSource;
+ }
+
+ @Bean(name = "sqlSessionFactory")
+ public SqlSessionFactoryBean sqlSessionFactory() {
+ SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
+ ssfb.setDataSource(dataSource());
+ ssfb.setTypeAliasesPackage("com.ifish.bean");
+ try {
+ org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
+ configuration.setMapUnderscoreToCamelCase(true);
+ ssfb.setConfiguration(configuration);
+
+ } catch (Exception e) {
+ }
+
+ return ssfb;
+ }
+
+ @Bean
+ public MapperScannerConfigurer mpperScannnerConfigurer() {
+ MapperScannerConfigurer msc = new MapperScannerConfigurer();
+ msc.setSqlSessionFactoryBeanName("sqlSessionFactory");
+ msc.setBasePackage("com.ifish.mapper");
+ return msc;
+ }
+
+ @Bean
+ PlatformTransactionManager transactionManager() {
+ DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
+ transactionManager.setDataSource(dataSource());
+ return transactionManager;
+ }
+
+}
diff --git a/src/main/java/com/ifish/config/RedisConfig.java b/src/main/java/com/ifish/config/RedisConfig.java
new file mode 100644
index 0000000..1d37213
--- /dev/null
+++ b/src/main/java/com/ifish/config/RedisConfig.java
@@ -0,0 +1,58 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.config;
+
+import com.ifish.util.IfishFilePath;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+
+/**
+ *
+ * @author Administrator
+ */
+@Configuration
+public class RedisConfig {
+
+ @Bean
+ public RedisConnectionFactory redisCF() {
+ JedisConnectionFactory cf = new JedisConnectionFactory();
+
+// //获取当前操作系统(servers_os为服务器设置的属性JAVA_OPTS=%JAVA_OPTS% -Dservers_os=online84)
+// String servers_os = System.getProperty("servers_os") == null ? "" : System.getProperty("servers_os");
+ if (IfishFilePath.link_img_head.contains("ifish7")) {
+ //站点线上服务器
+ cf.setHostName("120.55.190.56");
+ cf.setPort(3796);
+ cf.setPassword("ifish7myredis");
+ } else {
+ //站点测试服务器
+ cf.setHostName("139.196.24.156");
+ cf.setPort(3796);
+ cf.setPassword("ifish7myredis");
+// FileUtil.writeLinesByLog("测试缓存连接");
+ }
+
+ return cf;
+ }
+
+ @Bean
+ public RedisTemplate redisTemplate(RedisConnectionFactory cf) {
+ RedisTemplate redis = new RedisTemplate();
+ redis.setConnectionFactory(cf);
+ return redis;
+ }
+
+ @Bean
+ public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory cf) {
+ StringRedisTemplate redis = new StringRedisTemplate();
+ redis.setConnectionFactory(cf);
+ return redis;
+ }
+}
diff --git a/src/main/java/com/ifish/config/RootConfig.java b/src/main/java/com/ifish/config/RootConfig.java
new file mode 100644
index 0000000..f2aaaa3
--- /dev/null
+++ b/src/main/java/com/ifish/config/RootConfig.java
@@ -0,0 +1,26 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.config;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.ComponentScan.Filter;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.context.annotation.Import;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+
+/**
+ *
+ * @author Administrator
+ */
+@Configuration
+//@Import(MybatisConfig.class) //导入数据库文件配置
+@ComponentScan(basePackages = {"com.ifish.*"},
+ excludeFilters = {
+ @Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)})
+public class RootConfig {
+
+}
diff --git a/src/main/java/com/ifish/config/WebAppInitializer.java b/src/main/java/com/ifish/config/WebAppInitializer.java
new file mode 100644
index 0000000..af5c16c
--- /dev/null
+++ b/src/main/java/com/ifish/config/WebAppInitializer.java
@@ -0,0 +1,46 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.config;
+
+import javax.servlet.Filter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.filter.CharacterEncodingFilter;
+import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
+
+/**
+ *
+ * @author Administrator
+ */
+public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
+
+ @Override
+ protected Class>[] getRootConfigClasses() {
+ return new Class>[]{RootConfig.class, MybatisConfig.class,MinaConfig.class};
+ }
+
+ @Override
+ protected Class>[] getServletConfigClasses() {
+ return new Class>[]{WebConfig.class};
+ }
+
+ @Override
+ protected String[] getServletMappings() {
+ return new String[]{"/api/*"};
+ }
+
+ @Override
+ protected Filter[] getServletFilters() {
+ return null;
+ }
+
+ @Bean
+ public Filter characterEncodingFilter() {
+ CharacterEncodingFilter filter = new CharacterEncodingFilter();
+ filter.setEncoding("UTF-8");
+ filter.setForceEncoding(true);
+ return filter;
+ }
+}
diff --git a/src/main/java/com/ifish/config/WebConfig.java b/src/main/java/com/ifish/config/WebConfig.java
new file mode 100644
index 0000000..9771e0a
--- /dev/null
+++ b/src/main/java/com/ifish/config/WebConfig.java
@@ -0,0 +1,59 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.config;
+
+import com.ifish.util.IfishFilePath;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.ViewResolver;
+import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.view.InternalResourceViewResolver;
+
+/**
+ *
+ * @author Administrator
+ */
+@Configuration
+/**
+ * 启动SpringMVC
+ */
+@EnableWebMvc
+/**
+ * 启动组件扫描器,com.mymvc.controller是包
+ */
+@ComponentScan("com.ifish.controller")
+public class WebConfig extends WebMvcConfigurerAdapter {
+
+ /**
+ * 配置视图解析器
+ *
+ * @return
+ */
+ @Bean
+ public ViewResolver viewResolver() {
+ InternalResourceViewResolver resolver = new InternalResourceViewResolver();
+ resolver.setPrefix("/WEB-INF/views/");
+ resolver.setSuffix(".jsp");
+ resolver.setExposeContextBeansAsAttributes(true);
+ return resolver;
+ }
+
+ /**
+ * 配置静态资源的处理
+ *
+ * @param configurer
+ */
+ @Override
+ public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
+ configurer.enable();;
+ }
+
+
+}
diff --git a/src/main/java/com/ifish/enums/PushTypeEnum.java b/src/main/java/com/ifish/enums/PushTypeEnum.java
new file mode 100644
index 0000000..4ffa4e8
--- /dev/null
+++ b/src/main/java/com/ifish/enums/PushTypeEnum.java
@@ -0,0 +1,33 @@
+package com.ifish.enums;
+
+public enum PushTypeEnum {
+ remove_device("remove_device","解绑通知"),
+ wendu_warn("wendu_warn","温度报警"),
+ qu_reply("qu_reply","问题反馈"),
+ app_update("app_update","IOS更新推送"),
+ remind_water("remind_water","换水提醒"),
+ offline_push("offline_push","离线通知");
+
+ private PushTypeEnum(String key,String value){
+ this.key = key;
+ this.value = value;
+ }
+
+ private String key;
+ private String value;
+
+
+ public String getKey() {
+ return key;
+ }
+ public void setKey(String key) {
+ this.key = key;
+ }
+ public String getValue() {
+ return value;
+ }
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+}
diff --git a/src/main/java/com/ifish/enums/SubDirectoryEnum.java b/src/main/java/com/ifish/enums/SubDirectoryEnum.java
new file mode 100644
index 0000000..2715c25
--- /dev/null
+++ b/src/main/java/com/ifish/enums/SubDirectoryEnum.java
@@ -0,0 +1,45 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.enums;
+
+/**
+ *
+ * @author Administrator
+ */
+public enum SubDirectoryEnum {
+ headImage("app/", "头像"),
+ banner("banner/", "banner图"),
+ look("look/", "看护报告"),
+ ueditorHtml("ueditorHtml/", "后台生成的网页"),
+ adInfo("Img/adInfo/", "广告图片"),
+ information("Img/information/", "资讯图片"),
+ ifishGoods("Img/goods/", "商品图片"),
+ ifishCommodity("Img/commodity/", "商家商品介绍图");
+
+ private SubDirectoryEnum(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ private String key;
+ private String value;
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
diff --git a/src/main/java/com/ifish/helper/DeviceHelperI.java b/src/main/java/com/ifish/helper/DeviceHelperI.java
new file mode 100644
index 0000000..f3bf135
--- /dev/null
+++ b/src/main/java/com/ifish/helper/DeviceHelperI.java
@@ -0,0 +1,41 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.helper;
+
+import com.ifish.bean.LoginRecord;
+import com.ifish.bean.Tbl_Device;
+import com.ifish.bean.Tbl_Device_User;
+import com.ifish.bean.Tbl_Factory_List;
+import com.ifish.bean.Tbl_HardWare_Type;
+import com.ifish.socket.model.send.DeviceLoginContextLength24;
+import java.util.List;
+
+/**
+ *
+ * @author Administrator
+ */
+public interface DeviceHelperI {
+
+ public Tbl_Device update(Tbl_Device device);
+
+ public Tbl_Device update(DeviceLoginContextLength24 model);
+
+ public void updateWarnOnoff(String macAddress, String onOff);
+
+ public Tbl_Device getUniqueByProperty(String property, Object value);
+
+ public List getByProperty(String property, Object value);
+
+ public Tbl_Device_User getUniqueByProperty(String macAddress);
+
+ public List getListByProperty(Integer deviceId);
+
+ public LoginRecord save(LoginRecord loginRecord);
+
+ public Tbl_Factory_List getFactoryListById(String factoryCode);
+
+ public Tbl_HardWare_Type getHardwareTypeById(String typeCode);
+}
diff --git a/src/main/java/com/ifish/helper/UserHelperI.java b/src/main/java/com/ifish/helper/UserHelperI.java
new file mode 100644
index 0000000..3470650
--- /dev/null
+++ b/src/main/java/com/ifish/helper/UserHelperI.java
@@ -0,0 +1,20 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.helper;
+
+import com.ifish.bean.Tbl_Push_List;
+import com.ifish.bean.Tbl_User;
+
+/**
+ *
+ * @author Administrator
+ */
+public interface UserHelperI {
+
+ public Tbl_User findById(Integer userId);
+
+ public Tbl_Push_List save(Tbl_Push_List pushList);
+}
diff --git a/src/main/java/com/ifish/socket/codeFactory/Context.java b/src/main/java/com/ifish/socket/codeFactory/Context.java
new file mode 100644
index 0000000..3d632d2
--- /dev/null
+++ b/src/main/java/com/ifish/socket/codeFactory/Context.java
@@ -0,0 +1,58 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.codeFactory;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import org.apache.mina.core.buffer.IoBuffer;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Context {
+
+ private final CharsetDecoder decoder;
+ private IoBuffer buf;
+ private int matchCount = 0;
+ private int overflowPosition = 0;
+
+ public Context(Charset charset) {
+ decoder = charset.newDecoder();
+ buf = IoBuffer.allocate(100).setAutoExpand(true);
+ //buf.order(ByteOrder.LITTLE_ENDIAN);
+ }
+
+ public CharsetDecoder getDecoder() {
+ return decoder;
+ }
+
+ public IoBuffer getBuffer() {
+ return buf;
+ }
+
+ public int getOverflowPosition() {
+ return overflowPosition;
+ }
+
+ public int getMatchCount() {
+ return matchCount;
+ }
+
+ public void setMatchCount(int matchCount) {
+ this.matchCount = matchCount;
+ }
+
+ public void reset() {
+ overflowPosition = 0;
+ matchCount = 0;
+ decoder.reset();
+ }
+
+ public void append(IoBuffer in) {
+ getBuffer().put(in);
+ }
+}
diff --git a/src/main/java/com/ifish/socket/codeFactory/ServerCodecFactory.java b/src/main/java/com/ifish/socket/codeFactory/ServerCodecFactory.java
new file mode 100644
index 0000000..897b763
--- /dev/null
+++ b/src/main/java/com/ifish/socket/codeFactory/ServerCodecFactory.java
@@ -0,0 +1,31 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.codeFactory;
+
+import java.nio.charset.Charset;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+
+/**
+ *
+ * @author Administrator
+ */
+public class ServerCodecFactory implements ProtocolCodecFactory {
+
+ private static final Charset charset = Charset.forName("UTF-8");
+
+ @Override
+ public ProtocolDecoder getDecoder(IoSession session) throws Exception {
+ return new ServerDecode(charset);
+ }
+
+ @Override
+ public ProtocolEncoder getEncoder(IoSession session) throws Exception {
+ return new ServerEncode(charset);
+ }
+}
diff --git a/src/main/java/com/ifish/socket/codeFactory/ServerDecode.java b/src/main/java/com/ifish/socket/codeFactory/ServerDecode.java
new file mode 100644
index 0000000..5cc6dd2
--- /dev/null
+++ b/src/main/java/com/ifish/socket/codeFactory/ServerDecode.java
@@ -0,0 +1,385 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.codeFactory;
+
+import com.ifish.socket.model.send.DeviceLoginContextLength24;
+import com.ifish.socket.model.send.APPLoginContextLength25;
+import com.ifish.socket.model.send.ModelVersionLength22;
+import com.ifish.socket.model.send.ModelVersionLength38;
+import com.ifish.socket.model.send.TemperatureAlarmLength22;
+import com.ifish.socket.model.send.TemperatureSwitchLength22;
+import java.nio.charset.Charset;
+import org.apache.mina.core.buffer.IoBuffer;
+import org.apache.mina.core.session.AttributeKey;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 解码
+ *
+ * @author
+ */
+public class ServerDecode implements ProtocolDecoder {
+
+ private final AttributeKey CONTEXT = new AttributeKey(getClass(), "context");
+ private final Charset charset;
+ private static Logger log = LoggerFactory.getLogger(ServerDecode.class);
+
+ public ServerDecode() {
+ this(Charset.defaultCharset());
+ }
+
+ public ServerDecode(Charset charset) {
+ this.charset = charset;
+ }
+
+ private Context getContext(IoSession session) {
+ Context ctx = (Context) session.getAttribute(CONTEXT);
+ if (ctx == null) {
+ ctx = new Context(charset);
+ session.setAttribute(CONTEXT, ctx);
+ }
+ return ctx;
+ }
+
+ @Override
+ public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
+ // 小端模式
+ //in.order(ByteOrder.LITTLE_ENDIAN);
+ // 先获取上次的处理上下文,其中可能有未处理完的数据
+ Context ctx = getContext(session);
+ // 先把当前buffer中的数据追加到Context的buffer当中
+ ctx.append(in);
+
+ IoBuffer buf = ctx.getBuffer();
+ buf.flip();
+ //验证
+ getValid(session, buf, out);
+ }
+
+ /**
+ * 验证协议
+ *
+ * @param session
+ * @param buf
+ * @param out
+ */
+ private void getValid(IoSession session, IoBuffer buf, ProtocolDecoderOutput out) {
+ int limit = buf.remaining();
+ int check_code = buf.position(1).get() & 0xff;
+ int length = buf.position(14).get() & 0xff;
+ buf.position(0);
+ //计算包长度
+ if (buf.hasRemaining() && limit == length && length >= 17) {
+ //字节转成对象
+ doDecode(buf, out, length, check_code);
+ } else {
+ log.info("length error:length:【{}】,limit:【{}】,HexDump:【{}】", length, limit, buf.getHexDump());
+ }
+ buf.position(0);
+ buf.clear();
+ }
+
+ /**
+ * 解码成对象
+ *
+ * @param buf
+ * @param out
+ * @param length
+ */
+ private void doDecode(IoBuffer buf, ProtocolDecoderOutput out, int length, int check_code) {
+ //字节
+ byte[] bytes = new byte[length];
+ buf.get(bytes);
+ buf.flip();
+ //log.info("length:【{}】;limit:【{}】,HexDump:【{}】",length,buf.limit(),buf.getHexDump());
+ //crc16校验
+ //boolean bln = CRC16.calcCrc16(ByteUtil.hexStringToBytes(hexDump));
+ switch (length) {
+ //长度为22
+ case 22: {
+ //设置报警温度开关
+ if (check_code == 5) {
+ TemperatureSwitch(buf, out);
+ } //设备报警
+ else if (check_code == 9) {
+ TemperatureAlarm(buf, out);
+ } //模块版本指令
+ else if (check_code == 16) {
+ ModelVersion(buf, out);
+ } else {
+ out.write(bytes);
+ }
+ break;
+ }
+ //长度为24,设备发登录请求
+ case 24: {
+ if (check_code == 1) {
+ DeviceLogin(buf, out);
+ }
+ break;
+ }
+ //长度为25,手机发登录请求
+ case 25: {
+ if (check_code == 0) {
+ AppLogin(buf, out);
+ }
+ break;
+ }
+ //模块版本指令
+ case 42: {
+ if (check_code == 17) {
+ ModelVersion17(buf, out);
+ }
+ break;
+ }
+ default: {
+ out.write(bytes);
+ }
+ }
+ }
+
+ /**
+ * 设备登陆服务器
+ *
+ * @param buf
+ * @param out
+ */
+ private void DeviceLogin(IoBuffer buf, ProtocolDecoderOutput out) {
+ DeviceLoginContextLength24 model = new DeviceLoginContextLength24();
+ //15字节数据包头
+ model.setType(buf.get());
+ model.setCheck_code(buf.get());
+ byte[] src = model.getSrc();
+ for (int i = 0; i < src.length; i++) {
+ src[i] = buf.get();
+ }
+ model.setSrc(src);
+ byte[] dest = model.getDest();
+ for (int i = 0; i < dest.length; i++) {
+ dest[i] = buf.get();
+ }
+ model.setDest(dest);
+ model.setRemote_len(buf.get());
+ //登陆信息
+ model.setVendor(buf.get());
+ model.setHardware_type(buf.get());
+ model.setVersion(buf.get());
+ byte[] login_ip = model.getLogin_ip();
+ for (int i = 0; i < login_ip.length; i++) {
+ login_ip[i] = buf.get();
+ }
+ model.setLogin_ip(login_ip);
+ byte[] crc16_code = model.getCrc16_code();
+ for (int i = 0; i < crc16_code.length; i++) {
+ crc16_code[i] = buf.get();
+ }
+ out.write(model);
+ }
+
+ /**
+ * APP登陆服务器
+ *
+ * @param buf
+ * @param out
+ */
+ private void AppLogin(IoBuffer buf, ProtocolDecoderOutput out) {
+ APPLoginContextLength25 model = new APPLoginContextLength25();
+ //15字节数据包头
+ model.setType(buf.get());
+ model.setCheck_code(buf.get());
+ byte[] src = model.getSrc();
+ for (int i = 0; i < src.length; i++) {
+ src[i] = buf.get();
+ }
+ model.setSrc(src);
+ byte[] dest = model.getDest();
+ for (int i = 0; i < dest.length; i++) {
+ dest[i] = buf.get();
+ }
+ model.setDest(dest);
+ model.setRemote_len(buf.get());
+ //时间
+ model.setLongtime(buf.getLong());
+ byte[] crc16_code = model.getCrc16_code();
+ for (int i = 0; i < crc16_code.length; i++) {
+ crc16_code[i] = buf.get();
+ }
+ out.write(model);
+ }
+
+ /**
+ * 设置报警温度开关
+ *
+ * @param buf
+ * @param out
+ */
+ private void TemperatureSwitch(IoBuffer buf, ProtocolDecoderOutput out) {
+ TemperatureSwitchLength22 model = new TemperatureSwitchLength22();
+ //15字节数据包头
+ model.setType(buf.get());
+ model.setCheck_code(buf.get());
+ byte[] src = model.getSrc();
+ for (int i = 0; i < src.length; i++) {
+ src[i] = buf.get();
+ }
+ model.setSrc(src);
+ byte[] dest = model.getDest();
+ for (int i = 0; i < dest.length; i++) {
+ dest[i] = buf.get();
+ }
+ model.setDest(dest);
+ model.setRemote_len(buf.get());
+ //开启关闭报警,00关,01开,02设置温度
+ model.setOnoff(buf.get());
+ //低温报警温度
+ model.setLow_wendu(buf.getShort());
+ //高温报警温度
+ model.setHight_wendu(buf.getShort());
+ byte[] crc16_code = model.getCrc16_code();
+ for (int i = 0; i < crc16_code.length; i++) {
+ crc16_code[i] = buf.get();
+ }
+ out.write(model);
+ }
+
+ /**
+ * 模块版本号
+ *
+ * @param buf
+ * @param out
+ */
+ private void ModelVersion(IoBuffer buf, ProtocolDecoderOutput out) {
+ ModelVersionLength22 model = new ModelVersionLength22();
+ //15字节数据包头
+ model.setType(buf.get());
+ model.setCheck_code(buf.get());
+ byte[] src = model.getSrc();
+ for (int i = 0; i < src.length; i++) {
+ src[i] = buf.get();
+ }
+ model.setSrc(src);
+ byte[] dest = model.getDest();
+ for (int i = 0; i < dest.length; i++) {
+ dest[i] = buf.get();
+ }
+ model.setDest(dest);
+ model.setRemote_len(buf.get());
+ //版本
+ model.setVersion(buf.get());
+ //年
+ model.setYear(buf.getShort());
+ //月
+ model.setMonth(buf.get());
+ //日
+ model.setDay(buf.get());
+ byte[] crc16_code = model.getCrc16_code();
+ for (int i = 0; i < crc16_code.length; i++) {
+ crc16_code[i] = buf.get();
+ }
+ out.write(model);
+ }
+
+ /**
+ * 模块版本号
+ *
+ * @param buf
+ * @param out
+ */
+ private void ModelVersion17(IoBuffer buf, ProtocolDecoderOutput out) {
+ ModelVersionLength38 model = new ModelVersionLength38();
+ //15字节数据包头
+ model.setType(buf.get());
+ model.setCheck_code(buf.get());
+ byte[] src = model.getSrc();
+ for (int i = 0; i < src.length; i++) {
+ src[i] = buf.get();
+ }
+ model.setSrc(src);
+ byte[] dest = model.getDest();
+ for (int i = 0; i < dest.length; i++) {
+ dest[i] = buf.get();
+ }
+ model.setDest(dest);
+ model.setRemote_len(buf.get());
+ //版本
+ model.setVersion(buf.get());
+ //年
+ model.setYear(buf.getShort());
+ //月
+ model.setMonth(buf.get());
+ //日
+ model.setDay(buf.get());
+ //MCU启动次数
+ model.setNumber1(buf.getInt());
+ //模块启动次数
+ model.setNumber2(buf.getInt());
+ //连接路由器次数
+ model.setNumber3(buf.getInt());
+ //成功连接服务器次数
+ model.setNumber4(buf.getInt());
+ //尝试连接服务器次数
+ model.setNumber5(buf.getInt());
+ byte[] crc16_code = model.getCrc16_code();
+ for (int i = 0; i < crc16_code.length; i++) {
+ crc16_code[i] = buf.get();
+ }
+ out.write(model);
+ }
+
+ /**
+ * 设备温度报警
+ *
+ * @param buf
+ * @param out
+ */
+ private void TemperatureAlarm(IoBuffer buf, ProtocolDecoderOutput out) {
+ TemperatureAlarmLength22 model = new TemperatureAlarmLength22();
+ //15字节数据包头
+ model.setType(buf.get());
+ model.setCheck_code(buf.get());
+ byte[] src = model.getSrc();
+ for (int i = 0; i < src.length; i++) {
+ src[i] = buf.get();
+ }
+ model.setSrc(src);
+ byte[] dest = model.getDest();
+ for (int i = 0; i < dest.length; i++) {
+ dest[i] = buf.get();
+ }
+ model.setDest(dest);
+ model.setRemote_len(buf.get());
+ //报警温度类型,0是低温报警,1是高温报警
+ model.setWarn_type(buf.get());
+ //当前设备温度
+ model.setWendu(buf.getShort());
+ //报警温度
+ model.setWarn_wendu(buf.getShort());
+ byte[] crc16_code = model.getCrc16_code();
+ for (int i = 0; i < crc16_code.length; i++) {
+ crc16_code[i] = buf.get();
+ }
+ out.write(model);
+ }
+
+ @Override
+ public void dispose(IoSession session) throws Exception {
+ Context ctx = (Context) session.getAttribute(CONTEXT);
+ if (ctx != null) {
+ session.removeAttribute(CONTEXT);
+ }
+ }
+
+ @Override
+ public void finishDecode(IoSession session, ProtocolDecoderOutput out)
+ throws Exception {
+
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/codeFactory/ServerEncode.java b/src/main/java/com/ifish/socket/codeFactory/ServerEncode.java
new file mode 100644
index 0000000..37f4926
--- /dev/null
+++ b/src/main/java/com/ifish/socket/codeFactory/ServerEncode.java
@@ -0,0 +1,137 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.codeFactory;
+
+import com.ifish.socket.model.receive.APPLoginResponseLength26;
+import com.ifish.socket.model.receive.DeviceLoginResponseLength25;
+import com.ifish.socket.model.receive.ServerHeartbeatLength17;
+import com.ifish.socket.model.send.UpgradeVersionLength78;
+import com.ifish.socket.model.send.TemperatureSwitchLength22;
+import java.nio.charset.Charset;
+import org.apache.mina.core.buffer.IoBuffer;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 编码
+ *
+ * @author
+ */
+public class ServerEncode implements ProtocolEncoder {
+
+ private final Charset charset;
+ private static Logger log = LoggerFactory.getLogger(ServerEncode.class);
+
+ public ServerEncode() {
+ this(Charset.defaultCharset());
+ }
+
+ public ServerEncode(Charset charset) {
+ this.charset = charset;
+ }
+
+ /* 这个message来自哪? */
+ @Override
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+
+ IoBuffer buffer = IoBuffer.allocate(100).setAutoExpand(true);
+ //修改此缓冲区的字节顺序,小端模式
+ //buffer.order(ByteOrder.LITTLE_ENDIAN);
+ //转发不做处理的数据
+ if (message instanceof byte[]) {
+ byte[] bytes = (byte[]) message;
+ buffer.put(bytes);
+ } //响应心跳
+ else if (message instanceof ServerHeartbeatLength17) {
+ ServerHeartbeatLength17 model = (ServerHeartbeatLength17) message;
+ //15字节数据包头
+ buffer.put(model.getType());
+ buffer.put(model.getCheck_code());
+ buffer.put(model.getSrc());
+ buffer.put(model.getDest());
+ buffer.put(model.getRemote_len());
+ //crc16校验码
+ buffer.put(model.getCrc16_code());
+ } //设置报警温度
+ else if (message instanceof TemperatureSwitchLength22) {
+ TemperatureSwitchLength22 model = (TemperatureSwitchLength22) message;
+ //15字节数据包头
+ buffer.put(model.getType());
+ buffer.put(model.getCheck_code());
+ buffer.put(model.getSrc());
+ buffer.put(model.getDest());
+ buffer.put(model.getRemote_len());
+ //开关
+ buffer.put(model.getOnoff());
+ //温度类型
+ buffer.putShort(model.getLow_wendu());
+ //报警温度
+ buffer.putShort(model.getHight_wendu());
+ //crc16校验码
+ buffer.put(model.getCrc16_code());
+ } //APP登录响应
+ else if (message instanceof APPLoginResponseLength26) {
+ APPLoginResponseLength26 model = (APPLoginResponseLength26) message;
+ //15字节数据包头
+ buffer.put(model.getType());
+ buffer.put(model.getCheck_code());
+ buffer.put(model.getSrc());
+ buffer.put(model.getDest());
+ buffer.put(model.getRemote_len());
+ //状态
+ buffer.put(model.getLogin_status());
+ //时间
+ buffer.putLong(model.getSysTime());
+ //crc16校验码
+ buffer.put(model.getCrc16_code());
+ } //设备登陆返回
+ else if (message instanceof DeviceLoginResponseLength25) {
+ DeviceLoginResponseLength25 model = (DeviceLoginResponseLength25) message;
+ //15字节数据包头
+ buffer.put(model.getType());
+ buffer.put(model.getCheck_code());
+ buffer.put(model.getSrc());
+ buffer.put(model.getDest());
+ buffer.put(model.getRemote_len());
+ //系统时间
+ buffer.put(model.getSysTime());
+ //crc16校验码
+ buffer.put(model.getCrc16_code());
+ } //升级
+ else if (message instanceof UpgradeVersionLength78) {
+ UpgradeVersionLength78 model = (UpgradeVersionLength78) message;
+ //15字节数据包头
+ buffer.put(model.getType());
+ buffer.put(model.getCheck_code());
+ buffer.put(model.getSrc());
+ buffer.put(model.getDest());
+ buffer.put(model.getRemote_len());
+ //版本
+ buffer.put(model.getVersion());
+ //地址
+ buffer.put(model.getAddress());
+ //crc16校验码
+ buffer.put(model.getCrc16_code());
+ }
+ buffer.flip();
+ /*
+ * 编码的方式就是按照短信协议拼 装字符串到IoBuffer 缓冲区,然后调用ProtocolEncoderOutput
+ * 的write()方法输出字节 流
+ */
+ //log.info("limit:【{}】,HexDump:【{}】",buffer.limit(),buffer.getHexDump());
+ out.write(buffer);
+ out.flush();
+ buffer.free();
+ }
+
+ @Override
+ public void dispose(IoSession session) throws Exception {
+
+ }
+}
diff --git a/src/main/java/com/ifish/socket/config/ExecuteJob.java b/src/main/java/com/ifish/socket/config/ExecuteJob.java
new file mode 100644
index 0000000..81f2658
--- /dev/null
+++ b/src/main/java/com/ifish/socket/config/ExecuteJob.java
@@ -0,0 +1,119 @@
+
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.config;
+
+import com.ifish.bean.Tbl_Device;
+import com.ifish.bean.Tbl_Device_Statistics;
+import com.ifish.bean.Tbl_Device_User;
+import com.ifish.bean.Tbl_Push_List;
+import com.ifish.bean.Tbl_User;
+import com.ifish.enums.PushTypeEnum;
+import com.ifish.helper.DeviceHelperI;
+import com.ifish.helper.UserHelperI;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.mina.core.session.IoSession;
+import org.quartz.Job;
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ *
+ * @author Administrator
+ */
+public class ExecuteJob implements Job {
+
+ private static Logger log = LoggerFactory.getLogger(ExecuteJob.class);
+ //@Autowired
+ //private NeteaseIM neteaseIM;
+ @Autowired
+ private UserHelperI userHelperI;
+ @Autowired
+ private DeviceHelperI deviceHelperI;
+
+ public void execute(JobExecutionContext context) throws JobExecutionException {
+ //任务传递的参数
+ JobDataMap dataMap = context.getJobDetail().getJobDataMap();
+ String macAddress = dataMap.getString("macAddress");
+ String timestamp = dataMap.getString("timestamp");
+ try {
+ //移除为null的连接
+ IoSession session_cz = SomeServer.sessions_cz.get(macAddress);
+ if (session_cz == null || session_cz.getRemoteAddress() == null) {
+ SomeServer.sessions_cz.remove(macAddress);
+ }
+ //设备是否存在
+ Tbl_Device device = deviceHelperI.getUniqueByProperty("macAddress", macAddress);
+ Tbl_Device_Statistics device_Statistics = null;
+ if (device != null) {
+ //记录次数
+ Integer number1 = device_Statistics.getMcuCount();
+ Integer number2 = device_Statistics.getModuleCount();
+ Integer number3 = device_Statistics.getRouterCount();
+ Integer number4 = device_Statistics.getServerCount();
+ Integer number5 = device_Statistics.getServerTryCount();
+ List list = deviceHelperI.getListByProperty(device.getDeviceId());
+ //是否被绑定
+ if (list != null) {
+ for (Tbl_Device_User deviceUser : list) {
+ Integer userId = deviceUser.getUserId();
+ String showName = deviceUser.getShowName();
+ String title = PushTypeEnum.offline_push.getValue();
+ String msg = "【" + title + "】你的水族箱“" + showName + "”于" + timestamp + "离线,请及时查看!";
+ //发送云信消息
+ boolean neteaseBln = false;
+// Map neteaseMap = neteaseIM.sendMsg("ifish", userId.toString(), msg);
+// if (neteaseMap != null) {
+// neteaseBln = neteaseMap.get("code").equals(NeteaseEnum.status200.getKey());
+// }
+ //IOS极光推送
+ boolean jpushIosBln = false;
+ //推送记录
+ Tbl_Push_List pushList = new Tbl_Push_List();
+ Integer deviceId = deviceUser.getDeviceId();
+ Tbl_User user = userHelperI.findById(userId);
+ if (user != null) {
+ String loginType = user.getLoginType();
+ if (loginType != null) {
+ Map map = new HashMap();
+ map.put("device_id", deviceId.toString());
+ map.put("device_name", showName);
+ map.put("timestamp", timestamp);
+ map.put("msg_type", PushTypeEnum.offline_push.getKey());
+ //推送记录
+ pushList.setUserId(userId);
+ pushList.setDeviceId(deviceId);
+ pushList.setPhoneType(loginType.toLowerCase());
+ pushList.setShowName(showName);
+ pushList.setPushType(PushTypeEnum.offline_push.getKey());
+ pushList.setJpushStatus(neteaseBln ? "1" : "0");
+ pushList.setPushTitle(title);
+ pushList.setPushContext(msg);
+ pushList.setCreateTime(new Date());
+ pushList.setMcuCount(number1);
+ pushList.setModularCount(number2);
+ pushList.setRouterCount(number3);
+ pushList.setServerCount(number4);
+ pushList.setServerTryCount(number5);
+ userHelperI.save(pushList);
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ log.error("error msg:{}", e.toString());
+ }
+ }
+}
diff --git a/src/main/java/com/ifish/socket/config/JobFactory.java b/src/main/java/com/ifish/socket/config/JobFactory.java
new file mode 100644
index 0000000..976a079
--- /dev/null
+++ b/src/main/java/com/ifish/socket/config/JobFactory.java
@@ -0,0 +1,31 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.config;
+
+import org.quartz.spi.TriggerFiredBundle;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
+import org.springframework.scheduling.quartz.AdaptableJobFactory;
+
+/**
+ *
+ * @author Administrator
+ */
+public class JobFactory extends AdaptableJobFactory {
+
+ @Autowired
+ private AutowireCapableBeanFactory capableBeanFactory;
+
+ @Override
+ protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
+ //调用父类的方法
+ Object jobInstance = super.createJobInstance(bundle);
+ //进行注入
+ capableBeanFactory.autowireBean(jobInstance);
+ return jobInstance;
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/config/MinaServerHandler.java b/src/main/java/com/ifish/socket/config/MinaServerHandler.java
new file mode 100644
index 0000000..e5824ce
--- /dev/null
+++ b/src/main/java/com/ifish/socket/config/MinaServerHandler.java
@@ -0,0 +1,126 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.config;
+
+import com.ifish.socket.model.JobGroup;
+import com.ifish.util.IfishUtil;
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.mina.core.service.IoHandlerAdapter;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.core.session.IoSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ *
+ * @author Administrator
+ */
+public class MinaServerHandler extends IoHandlerAdapter {
+
+ private final AtomicInteger atomicInt = new AtomicInteger();
+
+ private static Logger log = LoggerFactory.getLogger(MinaServerHandler.class);
+
+ @Autowired
+ private SomeServer someServer;
+ @Autowired
+ private ScheduleJob scheduleJob;
+
+ @Override
+ public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
+ cause.printStackTrace();
+ log.error("{}服务器-客户端session异常:{}", session.getRemoteAddress(), cause.toString());
+ }
+
+ /**
+ * 服务端接收消息处理
+ */
+ @Override
+ public void messageReceived(IoSession session, Object message) throws Exception {
+ someServer.doSome(session, message);
+ }
+
+ /**
+ * 客户端连接的会话创建
+ */
+ @Override
+ public void sessionCreated(IoSession session) throws Exception {
+ log.info("{}:会话创建,在线数:{}", session.getRemoteAddress(), atomicInt.incrementAndGet());
+ }
+
+ /**
+ * 客户端连接关闭
+ */
+ @Override
+ public void sessionClosed(IoSession session) throws Exception {
+ log.warn("{}:会话关闭,连接数:{}", session.getRemoteAddress(), atomicInt.decrementAndGet());
+ //旧连接关闭,获取设备mac地址
+ String oldConnect = session.getRemoteAddress().toString();
+ String macAddress = SomeServer.remoteAddress.get(oldConnect);
+ if (macAddress != null) {
+ //移除关闭的连接
+ SomeServer.remoteAddress.remove(oldConnect);
+ //设备当前连接
+ IoSession nowIoSession = SomeServer.sessions_cz.get(macAddress);
+ if (nowIoSession != null && nowIoSession.getRemoteAddress() != null) {
+ String nowConnect = nowIoSession.getRemoteAddress().toString();
+ //如果当前连接和关闭的连接是相同的,说明设备没有重连,10分钟内还未连接,则推送通知用户
+ if (nowConnect.equals(oldConnect)) {
+ offlinePush(macAddress);
+ }
+ } //当前没有连接,10分钟内还未连接,则推送通知用户
+ else {
+ offlinePush(macAddress);
+ }
+ }
+ }
+
+ /**
+ * 延时10分钟推送离线通知,10分钟内重新连接上则移除推送,详见SomeServer
+ *
+ * @param macAddress
+ */
+ public void offlinePush(String macAddress) {
+ JobGroup jobGroup = new JobGroup();
+ jobGroup.setJobName(macAddress);
+ jobGroup.setTriggerName(macAddress);
+ jobGroup.setMacAddress(macAddress);
+ //离线时间
+ jobGroup.setTimestamp(IfishUtil.format(new Date()));
+ //10分钟后推送
+ jobGroup.setStartTime(new Date(new Date().getTime() + 600000L));
+ scheduleJob.addJob(jobGroup);
+ }
+
+ /**
+ * 给客户端发送消息
+ */
+ @Override
+ public void messageSent(IoSession session, Object message) {
+ //System.out.println("messageSent");
+ }
+
+ /**
+ * 空闲超时,主动关闭客户端连接
+ */
+ @Override
+ public void sessionIdle(IoSession session, IdleStatus status)
+ throws Exception {
+ log.warn("空闲超时,服务器主动关闭连接{}", session.getRemoteAddress());
+ session.close(true);
+ }
+
+ /**
+ * 客户端连接打开
+ */
+ @Override
+ public void sessionOpened(IoSession session) throws Exception {
+ //log.info("session open!!!");
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/config/MyInetSocketAddress.java b/src/main/java/com/ifish/socket/config/MyInetSocketAddress.java
new file mode 100644
index 0000000..2260d5e
--- /dev/null
+++ b/src/main/java/com/ifish/socket/config/MyInetSocketAddress.java
@@ -0,0 +1,53 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.config;
+
+import java.net.InetSocketAddress;
+
+/**
+ *
+ * @author Administrator
+ */
+public class MyInetSocketAddress {
+
+ private InetSocketAddress socketAddress = null;
+ private String ip = "";
+ private int serverPort = 9955;
+
+ public MyInetSocketAddress(String ip, int serverPort) {
+ try {
+ this.ip = ip;
+ this.serverPort = serverPort;
+ socketAddress = new InetSocketAddress(ip, serverPort);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public InetSocketAddress getSocketAddress() {
+ return socketAddress;
+ }
+
+ public void setSocketAddress(InetSocketAddress socketAddress) {
+ this.socketAddress = socketAddress;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public int getServerPort() {
+ return serverPort;
+ }
+
+ public void setServerPort(int serverPort) {
+ this.serverPort = serverPort;
+ }
+}
diff --git a/src/main/java/com/ifish/socket/config/ScheduleJob.java b/src/main/java/com/ifish/socket/config/ScheduleJob.java
new file mode 100644
index 0000000..684dfaa
--- /dev/null
+++ b/src/main/java/com/ifish/socket/config/ScheduleJob.java
@@ -0,0 +1,114 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.config;
+
+import com.ifish.socket.model.JobGroup;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import org.quartz.JobBuilder;
+import org.quartz.JobDetail;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.SchedulerFactory;
+import org.quartz.Trigger;
+import org.quartz.TriggerBuilder;
+import org.quartz.TriggerKey;
+import org.quartz.impl.StdSchedulerFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ *
+ * @author Administrator
+ */
+public class ScheduleJob {
+
+ private static Logger log = LoggerFactory.getLogger(ScheduleJob.class);
+ //调度
+ private Scheduler scheduler = null;
+
+ @Autowired
+ private JobFactory jobFactory;
+
+ @PostConstruct //初始化方法的注解方式 等同与init-method=init
+ public void init() {
+ try {
+ //调度任务开启
+ SchedulerFactory sf = new StdSchedulerFactory();
+ scheduler = sf.getScheduler();
+ //实现job中注入bean
+ scheduler.setJobFactory(jobFactory);
+ scheduler.start();
+ } catch (SchedulerException e) {
+ log.error("start scheduler error:{}", e.toString());
+ }
+ }
+
+ /**
+ * 添加任务
+ *
+ * @param jobGroup
+ * @throws SchedulerException
+ */
+ public void addJob(JobGroup jobGroup) {
+ try {
+ log.info("添加任务:{}.{}", jobGroup.getJobName(), jobGroup.getTriggerName());
+ //任务
+ JobDetail jobDetail = JobBuilder.newJob(ExecuteJob.class)
+ .usingJobData("macAddress", jobGroup.getMacAddress())
+ .usingJobData("timestamp", jobGroup.getTimestamp())
+ .withIdentity(jobGroup.getJobName(), jobGroup.getJobName())
+ .build();
+ //触发器
+ Trigger trigger = TriggerBuilder.newTrigger()
+ .withIdentity(jobGroup.getTriggerName(), jobGroup.getTriggerGroup())
+ .startAt(jobGroup.getStartTime()).build();
+ //添加触发器
+ scheduler.scheduleJob(jobDetail, trigger);
+ } catch (SchedulerException e) {
+ log.error("addJob error【macAddress:{},jobGroup:{},triggerGroup:{},errMsg:{}】", jobGroup.getMacAddress(), jobGroup.getJobName(), jobGroup.getTriggerGroup(), e.toString());
+ }
+ }
+
+ /**
+ * 移除任务
+ *
+ * @param jobGroup
+ * @throws SchedulerException
+ */
+ public void deleteJob(JobGroup jobGroup) {
+ try {
+ log.info("移除任务:{}.{}", jobGroup.getJobName(), jobGroup.getTriggerName());
+ //触发器
+ TriggerKey triggerKey = TriggerKey.triggerKey(jobGroup.getTriggerName(), jobGroup.getTriggerGroup());
+ //停止触发器
+ scheduler.pauseTrigger(triggerKey);
+ //移除触发器
+ scheduler.unscheduleJob(triggerKey);
+ //任务
+ JobKey jobKey = JobKey.jobKey(jobGroup.getJobName(), jobGroup.getJobGroup());
+ //删除任务
+ scheduler.deleteJob(jobKey);
+ } catch (SchedulerException e) {
+ log.error("deleteJob error【macAddress:{},jobGroup:{},triggerGroup:{},errMsg:{}】", jobGroup.getMacAddress(), jobGroup.getJobName(), jobGroup.getTriggerGroup(), e.toString());
+ }
+ }
+
+ /**
+ * 关闭调度任务
+ */
+ @PreDestroy //销毁方法的注解方式 等同于destory-method=destory222
+ public void shutdown() {
+ try {
+ //关闭任务
+ scheduler.shutdown();
+ } catch (SchedulerException e) {
+ log.error("shutdown scheduler error:{}", e.toString());
+ }
+ }
+}
diff --git a/src/main/java/com/ifish/socket/config/SomeServer.java b/src/main/java/com/ifish/socket/config/SomeServer.java
new file mode 100644
index 0000000..3deb2eb
--- /dev/null
+++ b/src/main/java/com/ifish/socket/config/SomeServer.java
@@ -0,0 +1,364 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.config;
+
+import com.ifish.bean.LoginRecord;
+import com.ifish.bean.Tbl_Device;
+import com.ifish.bean.Tbl_Device_Statistics;
+import com.ifish.bean.Tbl_Device_User;
+import com.ifish.bean.Tbl_Push_List;
+import com.ifish.bean.Tbl_User;
+import com.ifish.enums.PushTypeEnum;
+import com.ifish.helper.DeviceHelperI;
+import com.ifish.helper.UserHelperI;
+import com.ifish.socket.model.JobGroup;
+import com.ifish.socket.model.OrderModel;
+import com.ifish.socket.model.receive.APPLoginResponseLength26;
+import com.ifish.socket.model.receive.DeviceLoginResponseLength25;
+import com.ifish.socket.model.receive.ServerHeartbeatLength17;
+import com.ifish.socket.model.send.DeviceLoginContextLength24;
+import com.ifish.socket.model.send.ModelVersionLength22;
+import com.ifish.socket.model.send.ModelVersionLength38;
+import com.ifish.socket.model.send.TemperatureAlarmLength22;
+import com.ifish.socket.model.send.TemperatureSwitchLength22;
+import com.ifish.socket.model.send.UpgradeVersionLength78;
+import com.ifish.util.ByteUtil;
+import com.ifish.util.IfishUtil;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+import org.apache.mina.core.session.IoSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ *
+ * @author Administrator
+ */
+public class SomeServer {
+
+ @Autowired
+ private UserHelperI userHelperI;
+ @Autowired
+ private DeviceHelperI deviceHelperI;
+ @Autowired
+ private ScheduleJob scheduleJob;
+// @Autowired
+// private NeteaseIM neteaseIM;
+
+ //是否回复心跳
+ public static boolean isReplay = true;
+
+ private static Logger log = LoggerFactory.getLogger(SomeServer.class);
+ public static ConcurrentHashMap remoteAddress = new ConcurrentHashMap();
+ public static ConcurrentHashMap sessions_cz = new ConcurrentHashMap();
+ private ConcurrentHashMap> sessions_sjs = new ConcurrentHashMap>();
+
+ /**
+ * 过滤收到的数据 服务器收到数据,进行协议类型匹配,如果不匹配,则不执行相应操作。
+ *
+ * @param session
+ * @param message
+ */
+ public void doSome(IoSession session, Object message) {
+ //通配字符串
+ if (message instanceof byte[]) {
+ byte[] bytes = (byte[]) message;
+ //长度
+ int length = bytes[14] & 0xff;
+ //mac地址
+ byte[] srcByte = new byte[6];
+ for (int i = 2; i < 8; i++) {
+ srcByte[i - 2] = bytes[i];
+ }
+ String strSrc = ByteUtil.bytesToHexString(srcByte);
+ //心跳
+ if (length >= 28) {
+ sendToApp(session, strSrc, message);
+ } else {
+ sendToDevice(session, strSrc, message);
+ }
+ } //设置设备温度报警
+ else if (message instanceof TemperatureSwitchLength22) {
+ TemperatureSwitchLength22 receive = (TemperatureSwitchLength22) message;
+ String strDest = ByteUtil.bytesToHexString(receive.getDest());
+ sendToDevice(session, strDest, message);
+ try {
+ Integer Onoff = receive.getOnoff() & 0xff;
+ if (Onoff == 1 || Onoff == 0) {
+ deviceHelperI.updateWarnOnoff(strDest, Onoff.toString());
+ } else {
+ log.error("error Onoff:{},macAddress:{}", Onoff, strDest);
+ }
+ } catch (Exception e) {
+ log.warn("set OrderSetWarnModel error:macAddress:{},error msg:{}", strDest, e.toString());
+ }
+ } //设备温度报警
+ else if (message instanceof TemperatureAlarmLength22) {
+ TemperatureAlarmLength22 receive = (TemperatureAlarmLength22) message;
+ String strSrc = ByteUtil.bytesToHexString(receive.getSrc());
+ //推送类型
+ Integer warnType = receive.getWarn_type() & 0xff;
+ if (warnType == 0) {
+ pushNotifcation(strSrc, PushTypeEnum.wendu_warn.getValue(), "温度达到" + (float) receive.getWendu() / 10f + "℃,已低于" + (float) receive.getWarn_wendu() / 10f + "℃,请及时查看!");
+ } else if (warnType == 1) {
+ pushNotifcation(strSrc, PushTypeEnum.wendu_warn.getValue(), "温度达到" + (float) receive.getWendu() / 10f + "℃,已高于" + (float) receive.getWarn_wendu() / 10f + "℃,请及时查看!");
+ } else {
+ log.error("error warn_type:{},macAddress:{}", warnType, strSrc);
+ }
+ } //设备登录服务器
+ else if (message instanceof DeviceLoginContextLength24) {
+ DeviceLoginContextLength24 receive = (DeviceLoginContextLength24) message;
+ byte[] srcBytes = receive.getSrc();
+ byte[] destBytes = receive.getDest();
+ String strSrc = ByteUtil.bytesToHexString(srcBytes);
+ //服务器回复设备登录请求
+ DeviceLoginResponseLength25 model = OrderModel.DeviceLoginResponseLength25(destBytes, srcBytes);
+ //直接往本次session写回去
+ session.write(model);
+ //保存连接
+ sessions_cz.put(strSrc, session);
+ remoteAddress.put(session.getRemoteAddress().toString(), strSrc);
+ //设备重新连接上,则移除延时推送的任务
+ JobGroup jobGroup = new JobGroup();
+ jobGroup.setJobName(strSrc);
+ jobGroup.setTriggerName(strSrc);
+ scheduleJob.deleteJob(jobGroup);
+ try {
+ //更新设备信息
+ deviceHelperI.update(receive);
+// if(device==null){
+// String HexDump = ByteUtil.toHex(receive.getType())+ByteUtil.toHex(receive.getCheck_code())+ByteUtil.bytesToHexString(receive.getSrc())+ByteUtil.bytesToHexString(destBytes)+ByteUtil.toHex(receive.getRemote_len())+ByteUtil.toHex(receive.getVendor())+ByteUtil.toHex(receive.getHardware_type())+ByteUtil.toHex(receive.getVersion())+ByteUtil.bytesToHexString(receive.getLogin_ip())+ByteUtil.bytesToHexString(receive.getCrc16_code());
+// log.error("HexDump:{}",HexDump);
+// log.error("factoryCode or hardwareType not exist:macAddress:{},factoryCode:{},hardwareType:{}",strSrc,ByteUtil.toHex(receive.getVendor()),ByteUtil.toHex(receive.getHardware_type()));
+// }
+// else{
+ //记录登录时间
+ LoginRecord loginRecord = new LoginRecord();
+ loginRecord.setMacAddress(strSrc);
+ loginRecord.setLoginTime(new Date());
+ deviceHelperI.save(loginRecord);
+// }
+ } catch (Exception e) {
+ log.warn("save device login error:macAddress:{},error msg:{}", strSrc, e.toString());
+ }
+ } //APP登录服务器
+ else if (message instanceof APPLoginResponseLength26) {
+ APPLoginResponseLength26 receive = (APPLoginResponseLength26) message;
+ byte[] srcBytes = receive.getSrc();
+ byte[] destBytes = receive.getDest();
+ String strDest = ByteUtil.bytesToHexString(receive.getDest());
+ //设备是否在线
+ IoSession tmpSession = sessions_cz.get(strDest);
+ //1表示在线,0表示离线
+ byte login_status = 0;
+ if (tmpSession != null && tmpSession.getRemoteAddress() != null) {
+ login_status = 1;
+ } else {
+ login_status = 0;
+ }
+ //服务器回复APP登录请求
+ APPLoginResponseLength26 model = OrderModel.APPLoginResponseLength26(destBytes, srcBytes, login_status);
+ session.write(model);
+ //保存APP连接
+ CopyOnWriteArraySet sessionSet = sessions_sjs.get(strDest);
+ if (sessionSet == null) {
+ sessionSet = new CopyOnWriteArraySet();
+ sessionSet.add(session);
+ sessions_sjs.put(strDest, sessionSet);
+ } else {
+ for (IoSession ioSession : sessionSet) {
+ if (ioSession == null || ioSession.getRemoteAddress() == null) {
+ sessionSet.remove(ioSession);
+ }
+ }
+ sessionSet.add(session);
+ }
+ } //模块版本号
+ else if (message instanceof ModelVersionLength22) {
+ ModelVersionLength22 receive = (ModelVersionLength22) message;
+ byte[] macBytes = receive.getSrc();
+ String strSrc = ByteUtil.bytesToHexString(macBytes);
+ try {
+ //查找设备
+ Tbl_Device device = deviceHelperI.getUniqueByProperty("macAddress", strSrc);
+ Tbl_Device_Statistics device_Statistics = null;
+ if (device != null) {
+ //是否升级
+ if (device_Statistics.getIsUpgrade().equals("1")) {
+ device_Statistics.setIsUpgrade("0");
+ device_Statistics.setUpgradeTime(new Date());
+ //升级版本
+ int upgradeVersion = Integer.valueOf(device_Statistics.getUpgradeVersion());
+ UpgradeVersionLength78 model = OrderModel.UpgradeVersionLength78(macBytes, upgradeVersion);
+ session.write(model);
+ }
+ //记录参数
+ device_Statistics.setSdkVersion(String.valueOf(receive.getVersion() & 0xff));
+ device_Statistics.setSdkTime(IfishUtil.StrToDate(receive.getYear() + "-" + (receive.getMonth() & 0xff) + "-" + (receive.getDay() & 0xff)));
+ deviceHelperI.update(device);
+ }
+ } catch (Exception e) {
+ log.warn("save device sdk version16 error:macAddress:{},error msg:{}", strSrc, e.toString());
+ }
+ } //模块版本号
+ else if (message instanceof ModelVersionLength38) {
+ ModelVersionLength38 receive = (ModelVersionLength38) message;
+ byte[] macBytes = receive.getSrc();
+ String strSrc = ByteUtil.bytesToHexString(macBytes);
+ try {
+ //查找设备
+ Tbl_Device device = deviceHelperI.getUniqueByProperty("macAddress", strSrc);
+ Tbl_Device_Statistics device_Statistics = null;
+ if (device != null) {
+ //是否升级
+ if (device_Statistics.getIsUpgrade().equals("1")) {
+ device_Statistics.setIsUpgrade("0");
+ device_Statistics.setUpgradeTime(new Date());
+ //升级版本
+ int upgradeVersion = Integer.parseInt(device_Statistics.getUpgradeVersion());
+ UpgradeVersionLength78 model = OrderModel.UpgradeVersionLength78(macBytes, upgradeVersion);
+ session.write(model);
+ }
+ //记录参数
+ device_Statistics.setSdkVersion(String.valueOf(receive.getVersion() & 0xff));
+ device_Statistics.setSdkTime(IfishUtil.StrToDate(receive.getYear() + "-" + (receive.getMonth() & 0xff) + "-" + (receive.getDay() & 0xff)));
+ device_Statistics.setMcuCount(receive.getNumber1());
+ device_Statistics.setModuleCount(receive.getNumber2());
+ device_Statistics.setRouterCount(receive.getNumber3());
+ device_Statistics.setServerCount(receive.getNumber4());
+ device_Statistics.setServerTryCount(receive.getNumber5());
+ deviceHelperI.update(device);
+ }
+ } catch (Exception e) {
+ log.warn("save device sdk version17 error:macAddress:{},error msg:{}", strSrc, e.toString());
+ }
+ }
+ }
+
+ /**
+ * 发送数据APP
+ *
+ * @param dest 目的地
+ * @param message 发送对象
+ * @return
+ */
+ public void sendToApp(IoSession session, String strDest, Object message) {
+ //回复设备
+ if (isReplay) {
+ ServerHeartbeatLength17 model = OrderModel.ServerHeartbeatLength17(strDest);
+ session.write(model);
+ }
+ //转发给APP
+ CopyOnWriteArraySet sessionSet = sessions_sjs.get(strDest);
+ if (sessionSet != null && sessionSet.size() > 0) {
+ for (IoSession sj_session : sessionSet) {
+ if (sj_session != null && sj_session.getRemoteAddress() != null) {
+ sj_session.write(message);
+ } else {
+ sessionSet.remove(sj_session);
+ }
+ }
+ }
+ }
+
+ /**
+ * 发送数据给设备
+ *
+ * @param dest 目的地
+ * @param message 发送对象
+ * @return
+ */
+ public void sendToDevice(IoSession session, String strDest, Object message) {
+ IoSession cz_session = sessions_cz.get(strDest);
+ if (cz_session != null && cz_session.getRemoteAddress() != null) {
+ cz_session.write(message);
+ } else {
+ //设备离线
+ byte[] bytes = ByteUtil.hexStringToBytes2(strDest);
+ APPLoginResponseLength26 model = OrderModel.APPLoginResponseLength26(bytes, bytes, (byte) 0);
+ session.write(model);
+ }
+ }
+
+ /**
+ * 温度预警推送
+ *
+ * @param strSrc
+ * @param title
+ * @param contont
+ */
+ public void pushNotifcation(String strSrc, String title, String contont) {
+ try {
+ //Device device = deviceService.getUniqueByProperty("macAddress", strSrc);
+ Tbl_Device device = deviceHelperI.getUniqueByProperty("macAddress", strSrc);
+ Tbl_Device_Statistics device_Statistics = null;
+ if (device != null) {
+ Integer deviceId = device.getDeviceId();
+ //是否开启预警
+ String onOff = device.getOnOff();
+ if (onOff != null && onOff.equals("1")) {
+ //绑定设备的用户
+ List list = deviceHelperI.getListByProperty(device.getDeviceId());
+ for (Tbl_Device_User deviceUser : list) {
+ Integer userId = deviceUser.getUserId();
+ String showName = deviceUser.getShowName();
+ String timestamp = IfishUtil.format(new Date());
+ String msg = "【" + title + "】你的水族箱“" + showName + "”在" + timestamp + contont;
+ Tbl_User user = userHelperI.findById(userId);
+ if (user != null) {
+ //云信推送
+ boolean neteaseBln = false;
+ //极光推送
+ boolean jpushIosBln = false;
+ boolean jpushAndroidBln = false;
+ //发送云信消息
+// Map neteaseMap = neteaseIM.sendMsg("ifish", userId.toString(), msg);
+// if (neteaseMap != null) {
+// neteaseBln = neteaseMap.get("code").equals(NeteaseEnum.status200.getKey());
+// }
+ String loginType = user.getLoginType();
+ if (loginType != null) {
+ //推送记录
+ Tbl_Push_List pushList = new Tbl_Push_List();
+ Map map = new HashMap();
+ map.put("device_id", deviceId.toString());
+ map.put("device_name", showName);
+ map.put("timestamp", timestamp);
+ map.put("msg_type", PushTypeEnum.wendu_warn.getKey());
+ //记录推送
+ if (jpushIosBln || jpushAndroidBln || neteaseBln) {
+ pushList.setUserId(userId);
+ pushList.setDeviceId(deviceId);
+ pushList.setPhoneType(loginType.toLowerCase());
+ pushList.setShowName(showName);
+ pushList.setPushType(PushTypeEnum.wendu_warn.getKey());
+ pushList.setPushTitle(title);
+ pushList.setPushContext(msg);
+ pushList.setJpushStatus(neteaseBln ? "1" : "0");
+ pushList.setCreateTime(new Date());
+ pushList.setMcuCount(device_Statistics.getMcuCount());
+ pushList.setModularCount(device_Statistics.getModuleCount());
+ pushList.setRouterCount(device_Statistics.getRouterCount());
+ pushList.setServerCount(device_Statistics.getServerCount());
+ pushList.setServerTryCount(device_Statistics.getServerTryCount());
+ userHelperI.save(pushList);
+ }
+ }
+ }
+ }
+
+ }
+ }
+ } catch (Exception e) {
+ log.warn("pushNotifcation error:macAddress:{},error msg:{}", strSrc, e.toString());
+ }
+ }
+}
diff --git a/src/main/java/com/ifish/socket/model/DeviceResponseLength99.java b/src/main/java/com/ifish/socket/model/DeviceResponseLength99.java
new file mode 100644
index 0000000..f83b8f8
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/DeviceResponseLength99.java
@@ -0,0 +1,500 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model;
+
+import java.io.Serializable;
+
+/**
+ *
+ * @author Administrator
+ */
+public class DeviceResponseLength99 extends HeadModel implements Serializable {
+
+ private static final long serialVersionUID = -2334084294686976805L;
+ //工作模式
+ private byte work_model;
+ /**
+ * *******灯和开关(10字节)*********
+ */
+ //灯编号1
+ private byte number1;
+ //灯编号2
+ private byte number2;
+ //灯编号3
+ private byte number3;
+ //灯编号4
+ private byte number4;
+ //灯编号5
+ private byte number5;
+ //灯1开关
+ private byte onoff1;
+ //灯2开关
+ private byte onoff2;
+ //灯3开关
+ private byte onoff3;
+ //灯4开关
+ private byte onoff4;
+ //灯5开关
+ private byte onoff5;
+ /**
+ * *******定时器编号(10字节)灯1对应定时器1-2,灯2对应定时器3-4,灯3对应定时器5-6*********
+ */
+ //定时器1编号
+ private byte timer_number1;
+ //定时器2编号
+ private byte timer_number2;
+ //定时器3编号
+ private byte timer_number3;
+ //定时器4编号
+ private byte timer_number4;
+ //定时器5编号
+ private byte timer_number5;
+ //定时器6编号
+ private byte timer_number6;
+ //定时器7编号
+ private byte timer_number7;
+ //定时器8编号
+ private byte timer_number8;
+ //定时器9编号
+ private byte timer_number9;
+ //定时器10编号
+ private byte timer_number10;
+ /**
+ * *******定时器开关(10字节)*********
+ */
+ //定时器1开关
+ private byte timer_onoff1;
+ //定时器2开关
+ private byte timer_onoff2;
+ //定时器3开关
+ private byte timer_onoff3;
+ //定时器4开关
+ private byte timer_onoff4;
+ //定时器5开关
+ private byte timer_onoff5;
+ //定时器6开关
+ private byte timer_onoff6;
+ //定时器7开关
+ private byte timer_onoff7;
+ //定时器8开关
+ private byte timer_onoff8;
+ //定时器9开关
+ private byte timer_onoff9;
+ //定时器10开关
+ private byte timer_onoff10;
+ /**
+ * *******定时器时间(40字节)*********
+ */
+ //定时器1时间
+ private byte[] timer_time1 = new byte[4];
+ //定时器2时间
+ private byte[] timer_time2 = new byte[4];
+ //定时器3时间
+ private byte[] timer_time3 = new byte[4];
+ //定时器4时间
+ private byte[] timer_time4 = new byte[4];
+ //定时器5时间
+ private byte[] timer_time5 = new byte[4];
+ //定时器6时间
+ private byte[] timer_time6 = new byte[4];
+ //定时器7时间
+ private byte[] timer_time7 = new byte[4];
+ //定时器8时间
+ private byte[] timer_time8 = new byte[4];
+ //定时器9时间
+ private byte[] timer_time9 = new byte[4];
+ //定时器10时间
+ private byte[] timer_time10 = new byte[4];
+ //温度
+ private short wendu;
+ //ph
+ private short ph_value;
+ //湿度
+ private short shidu;
+ //报警开关,0关,1开
+ private byte warn_onoff;
+ //最低报警温度
+ private short low_wendu;
+ //最高报警温度
+ private short high_wendu;
+
+ public short getWendu() {
+ return wendu;
+ }
+
+ public void setWendu(short wendu) {
+ this.wendu = wendu;
+ }
+
+ public byte getWork_model() {
+ return work_model;
+ }
+
+ public void setWork_model(byte work_model) {
+ this.work_model = work_model;
+ }
+
+ public byte getNumber1() {
+ return number1;
+ }
+
+ public void setNumber1(byte number1) {
+ this.number1 = number1;
+ }
+
+ public byte getOnoff1() {
+ return onoff1;
+ }
+
+ public void setOnoff1(byte onoff1) {
+ this.onoff1 = onoff1;
+ }
+
+ public byte getNumber2() {
+ return number2;
+ }
+
+ public void setNumber2(byte number2) {
+ this.number2 = number2;
+ }
+
+ public byte getOnoff2() {
+ return onoff2;
+ }
+
+ public void setOnoff2(byte onoff2) {
+ this.onoff2 = onoff2;
+ }
+
+ public byte getNumber3() {
+ return number3;
+ }
+
+ public void setNumber3(byte number3) {
+ this.number3 = number3;
+ }
+
+ public byte getOnoff3() {
+ return onoff3;
+ }
+
+ public void setOnoff3(byte onoff3) {
+ this.onoff3 = onoff3;
+ }
+
+ public byte getTimer_number1() {
+ return timer_number1;
+ }
+
+ public void setTimer_number1(byte timer_number1) {
+ this.timer_number1 = timer_number1;
+ }
+
+ public byte getTimer_number2() {
+ return timer_number2;
+ }
+
+ public void setTimer_number2(byte timer_number2) {
+ this.timer_number2 = timer_number2;
+ }
+
+ public byte getTimer_number3() {
+ return timer_number3;
+ }
+
+ public void setTimer_number3(byte timer_number3) {
+ this.timer_number3 = timer_number3;
+ }
+
+ public byte getTimer_number4() {
+ return timer_number4;
+ }
+
+ public void setTimer_number4(byte timer_number4) {
+ this.timer_number4 = timer_number4;
+ }
+
+ public byte getTimer_number5() {
+ return timer_number5;
+ }
+
+ public void setTimer_number5(byte timer_number5) {
+ this.timer_number5 = timer_number5;
+ }
+
+ public byte getTimer_number6() {
+ return timer_number6;
+ }
+
+ public void setTimer_number6(byte timer_number6) {
+ this.timer_number6 = timer_number6;
+ }
+
+ public byte getTimer_number7() {
+ return timer_number7;
+ }
+
+ public void setTimer_number7(byte timer_number7) {
+ this.timer_number7 = timer_number7;
+ }
+
+ public byte getTimer_number8() {
+ return timer_number8;
+ }
+
+ public void setTimer_number8(byte timer_number8) {
+ this.timer_number8 = timer_number8;
+ }
+
+ public byte getTimer_number9() {
+ return timer_number9;
+ }
+
+ public void setTimer_number9(byte timer_number9) {
+ this.timer_number9 = timer_number9;
+ }
+
+ public byte[] getTimer_time1() {
+ return timer_time1;
+ }
+
+ public void setTimer_time1(byte[] timer_time1) {
+ this.timer_time1 = timer_time1;
+ }
+
+ public byte[] getTimer_time2() {
+ return timer_time2;
+ }
+
+ public void setTimer_time2(byte[] timer_time2) {
+ this.timer_time2 = timer_time2;
+ }
+
+ public byte[] getTimer_time3() {
+ return timer_time3;
+ }
+
+ public void setTimer_time3(byte[] timer_time3) {
+ this.timer_time3 = timer_time3;
+ }
+
+ public byte[] getTimer_time4() {
+ return timer_time4;
+ }
+
+ public void setTimer_time4(byte[] timer_time4) {
+ this.timer_time4 = timer_time4;
+ }
+
+ public byte[] getTimer_time5() {
+ return timer_time5;
+ }
+
+ public void setTimer_time5(byte[] timer_time5) {
+ this.timer_time5 = timer_time5;
+ }
+
+ public byte[] getTimer_time6() {
+ return timer_time6;
+ }
+
+ public void setTimer_time6(byte[] timer_time6) {
+ this.timer_time6 = timer_time6;
+ }
+
+ public byte[] getTimer_time7() {
+ return timer_time7;
+ }
+
+ public void setTimer_time7(byte[] timer_time7) {
+ this.timer_time7 = timer_time7;
+ }
+
+ public byte[] getTimer_time8() {
+ return timer_time8;
+ }
+
+ public void setTimer_time8(byte[] timer_time8) {
+ this.timer_time8 = timer_time8;
+ }
+
+ public byte[] getTimer_time9() {
+ return timer_time9;
+ }
+
+ public void setTimer_time9(byte[] timer_time9) {
+ this.timer_time9 = timer_time9;
+ }
+
+ public short getPh_value() {
+ return ph_value;
+ }
+
+ public void setPh_value(short ph_value) {
+ this.ph_value = ph_value;
+ }
+
+ public short getShidu() {
+ return shidu;
+ }
+
+ public void setShidu(short shidu) {
+ this.shidu = shidu;
+ }
+
+ public byte getWarn_onoff() {
+ return warn_onoff;
+ }
+
+ public void setWarn_onoff(byte warn_onoff) {
+ this.warn_onoff = warn_onoff;
+ }
+
+ public short getLow_wendu() {
+ return low_wendu;
+ }
+
+ public void setLow_wendu(short low_wendu) {
+ this.low_wendu = low_wendu;
+ }
+
+ public short getHigh_wendu() {
+ return high_wendu;
+ }
+
+ public void setHigh_wendu(short high_wendu) {
+ this.high_wendu = high_wendu;
+ }
+
+ public byte getOnoff4() {
+ return onoff4;
+ }
+
+ public void setOnoff4(byte onoff4) {
+ this.onoff4 = onoff4;
+ }
+
+ public byte getOnoff5() {
+ return onoff5;
+ }
+
+ public void setOnoff5(byte onoff5) {
+ this.onoff5 = onoff5;
+ }
+
+ public byte getTimer_number10() {
+ return timer_number10;
+ }
+
+ public void setTimer_number10(byte timer_number10) {
+ this.timer_number10 = timer_number10;
+ }
+
+ public byte[] getTimer_time10() {
+ return timer_time10;
+ }
+
+ public void setTimer_time10(byte[] timer_time10) {
+ this.timer_time10 = timer_time10;
+ }
+
+ public byte getNumber4() {
+ return number4;
+ }
+
+ public void setNumber4(byte number4) {
+ this.number4 = number4;
+ }
+
+ public byte getNumber5() {
+ return number5;
+ }
+
+ public void setNumber5(byte number5) {
+ this.number5 = number5;
+ }
+
+ public byte getTimer_onoff1() {
+ return timer_onoff1;
+ }
+
+ public void setTimer_onoff1(byte timer_onoff1) {
+ this.timer_onoff1 = timer_onoff1;
+ }
+
+ public byte getTimer_onoff2() {
+ return timer_onoff2;
+ }
+
+ public void setTimer_onoff2(byte timer_onoff2) {
+ this.timer_onoff2 = timer_onoff2;
+ }
+
+ public byte getTimer_onoff3() {
+ return timer_onoff3;
+ }
+
+ public void setTimer_onoff3(byte timer_onoff3) {
+ this.timer_onoff3 = timer_onoff3;
+ }
+
+ public byte getTimer_onoff4() {
+ return timer_onoff4;
+ }
+
+ public void setTimer_onoff4(byte timer_onoff4) {
+ this.timer_onoff4 = timer_onoff4;
+ }
+
+ public byte getTimer_onoff5() {
+ return timer_onoff5;
+ }
+
+ public void setTimer_onoff5(byte timer_onoff5) {
+ this.timer_onoff5 = timer_onoff5;
+ }
+
+ public byte getTimer_onoff6() {
+ return timer_onoff6;
+ }
+
+ public void setTimer_onoff6(byte timer_onoff6) {
+ this.timer_onoff6 = timer_onoff6;
+ }
+
+ public byte getTimer_onoff7() {
+ return timer_onoff7;
+ }
+
+ public void setTimer_onoff7(byte timer_onoff7) {
+ this.timer_onoff7 = timer_onoff7;
+ }
+
+ public byte getTimer_onoff8() {
+ return timer_onoff8;
+ }
+
+ public void setTimer_onoff8(byte timer_onoff8) {
+ this.timer_onoff8 = timer_onoff8;
+ }
+
+ public byte getTimer_onoff9() {
+ return timer_onoff9;
+ }
+
+ public void setTimer_onoff9(byte timer_onoff9) {
+ this.timer_onoff9 = timer_onoff9;
+ }
+
+ public byte getTimer_onoff10() {
+ return timer_onoff10;
+ }
+
+ public void setTimer_onoff10(byte timer_onoff10) {
+ this.timer_onoff10 = timer_onoff10;
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/model/HeadModel.java b/src/main/java/com/ifish/socket/model/HeadModel.java
new file mode 100644
index 0000000..d0d0b44
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/HeadModel.java
@@ -0,0 +1,80 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model;
+
+import java.io.Serializable;
+
+/**
+ * 所有请求的数据包头,15字节数据包头+CRC16校验码2字节
+ *
+ * @author guogw
+ *
+ */
+public class HeadModel implements Serializable {
+
+ private static final long serialVersionUID = 7351497431272185642L;
+ //发送消息类型,1回复类型,0发送类型
+ private byte type;
+ //功能码
+ private byte check_code;
+ //6位为发送端的mac地址,高16位为0001
+ private byte[] src = new byte[6];
+ //6位为接收端的mac地址,高16位为0001
+ private byte[] dest = new byte[6];
+ //整个包长度
+ private byte remote_len;
+ //CRC16校验码
+ private byte[] crc16_code = new byte[2];
+
+ public byte getType() {
+ return type;
+ }
+
+ public void setType(byte type) {
+ this.type = type;
+ }
+
+ public byte getCheck_code() {
+ return check_code;
+ }
+
+ public void setCheck_code(byte check_code) {
+ this.check_code = check_code;
+ }
+
+ public void setRemote_len(byte remote_len) {
+ this.remote_len = remote_len;
+ }
+
+ public byte[] getSrc() {
+ return src;
+ }
+
+ public void setSrc(byte[] src) {
+ this.src = src;
+ }
+
+ public byte[] getDest() {
+ return dest;
+ }
+
+ public void setDest(byte[] dest) {
+ this.dest = dest;
+ }
+
+ public byte getRemote_len() {
+ return remote_len;
+ }
+
+ public byte[] getCrc16_code() {
+ return crc16_code;
+ }
+
+ public void setCrc16_code(byte[] crc16_code) {
+ this.crc16_code = crc16_code;
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/model/JobGroup.java b/src/main/java/com/ifish/socket/model/JobGroup.java
new file mode 100644
index 0000000..35fbc72
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/JobGroup.java
@@ -0,0 +1,107 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model;
+
+import java.util.Date;
+
+/**
+ *
+ * @author Administrator
+ */
+public class JobGroup {
+
+ /**
+ * 任务名称 *
+ */
+ private String jobName;
+
+ /**
+ * 任务分组 *
+ */
+ private String jobGroup = "offlinePushGroup";
+
+ /**
+ * 触发器名称 *
+ */
+ private String triggerName;
+
+ /**
+ * 触发器分组 *
+ */
+ private String triggerGroup = "offlinePushGroup";
+
+ /**
+ * mac地址 *
+ */
+ private String macAddress;
+
+ /**
+ * 执行时间 *
+ */
+ private Date startTime;
+
+ /**
+ * 离线时间 *
+ */
+ private String timestamp;
+
+ public String getJobName() {
+ return jobName;
+ }
+
+ public void setJobName(String jobName) {
+ this.jobName = jobName;
+ }
+
+ public String getJobGroup() {
+ return jobGroup;
+ }
+
+ public void setJobGroup(String jobGroup) {
+ this.jobGroup = jobGroup;
+ }
+
+ public String getTriggerName() {
+ return triggerName;
+ }
+
+ public void setTriggerName(String triggerName) {
+ this.triggerName = triggerName;
+ }
+
+ public String getTriggerGroup() {
+ return triggerGroup;
+ }
+
+ public void setTriggerGroup(String triggerGroup) {
+ this.triggerGroup = triggerGroup;
+ }
+
+ public String getMacAddress() {
+ return macAddress;
+ }
+
+ public void setMacAddress(String macAddress) {
+ this.macAddress = macAddress;
+ }
+
+ public Date getStartTime() {
+ return startTime;
+ }
+
+ public void setStartTime(Date startTime) {
+ this.startTime = startTime;
+ }
+
+ public String getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(String timestamp) {
+ this.timestamp = timestamp;
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/model/OrderModel.java b/src/main/java/com/ifish/socket/model/OrderModel.java
new file mode 100644
index 0000000..178693a
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/OrderModel.java
@@ -0,0 +1,101 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model;
+
+import com.ifish.socket.model.receive.APPLoginResponseLength26;
+import com.ifish.socket.model.receive.DeviceLoginResponseLength25;
+import com.ifish.socket.model.receive.ServerHeartbeatLength17;
+import com.ifish.socket.model.send.UpgradeVersionLength78;
+import com.ifish.util.ByteUtil;
+
+/**
+ *
+ * @author Administrator
+ */
+public class OrderModel {
+
+ /**
+ * 服务器回复设备登录请求指令
+ *
+ * @param src
+ * @param dest
+ * @return
+ */
+ public final static DeviceLoginResponseLength25 DeviceLoginResponseLength25(byte[] src, byte[] dest) {
+ DeviceLoginResponseLength25 model = new DeviceLoginResponseLength25();
+ model.setType((byte) 1);
+ model.setCheck_code((byte) 1);
+ model.setSrc(src);
+ model.setDest(dest);
+ model.setRemote_len((byte) 25);
+ model.setSysTime(ByteUtil.hexSysTime());
+ return model;
+ }
+
+ /**
+ * 服务器回复APP登录请求指令
+ *
+ * @param src
+ * @param dest
+ * @return
+ */
+ public final static APPLoginResponseLength26 APPLoginResponseLength26(byte[] src, byte[] dest, byte login_status) {
+ APPLoginResponseLength26 model = new APPLoginResponseLength26();
+ model.setType((byte) 1);
+ model.setSrc(src);
+ model.setDest(dest);
+ model.setRemote_len((byte) 26);
+ model.setLogin_status(login_status);
+ model.setSysTime(System.currentTimeMillis());
+ return model;
+ }
+
+ /**
+ * 获取查询命令
+ *
+ * @param type
+ * @param macAddress
+ * @return
+ */
+ public final static ServerHeartbeatLength17 ServerHeartbeatLength17(String macAddress) {
+ ServerHeartbeatLength17 model = new ServerHeartbeatLength17();
+ //15字节数据包头
+ model.setType((byte) 1);
+ model.setCheck_code((byte) 8);
+ model.setSrc(ByteUtil.hexStringToBytes2(macAddress));
+ model.setDest(ByteUtil.hexStringToBytes2(macAddress));
+ model.setRemote_len((byte) 17);
+ return model;
+ }
+
+ /**
+ * 升级
+ *
+ * @param type
+ * @param macAddress
+ * @param timer_number
+ * @param time
+ * @return
+ */
+ public final static UpgradeVersionLength78 UpgradeVersionLength78(byte[] macAddress, int version) {
+ UpgradeVersionLength78 model = new UpgradeVersionLength78();
+ //15字节数据包头
+ model.setType((byte) 0);
+ model.setCheck_code((byte) 15);
+ model.setSrc(macAddress);
+ model.setDest(macAddress);
+ model.setRemote_len((byte) 78);
+ model.setVersion((byte) version);
+ //地址
+ byte[] addressByte = model.getAddress();
+ byte[] bytes = "/download/sdk/".getBytes();
+ for (int i = 0; i < bytes.length; i++) {
+ addressByte[i] = bytes[i];
+ }
+ model.setAddress(addressByte);
+ return model;
+ }
+}
diff --git a/src/main/java/com/ifish/socket/model/receive/APPLoginResponseLength26.java b/src/main/java/com/ifish/socket/model/receive/APPLoginResponseLength26.java
new file mode 100644
index 0000000..ce51e39
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/receive/APPLoginResponseLength26.java
@@ -0,0 +1,41 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model.receive;
+
+import com.ifish.socket.model.HeadModel;
+import java.io.Serializable;
+
+/**
+ * 服务器回复手机端的登录请求26字节(17字节头+9字节)
+ *
+ * @author guogw
+ *
+ */
+public class APPLoginResponseLength26 extends HeadModel implements Serializable {
+
+ private static final long serialVersionUID = 656305903606196100L;
+ //0表示设备还未连接服务器,1表示已连接
+ private byte login_status;
+ //系统时间
+ private long sysTime;
+
+ public byte getLogin_status() {
+ return login_status;
+ }
+
+ public void setLogin_status(byte login_status) {
+ this.login_status = login_status;
+ }
+
+ public long getSysTime() {
+ return sysTime;
+ }
+
+ public void setSysTime(long sysTime) {
+ this.sysTime = sysTime;
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/model/receive/DeviceLoginResponseLength25.java b/src/main/java/com/ifish/socket/model/receive/DeviceLoginResponseLength25.java
new file mode 100644
index 0000000..7f4d0bb
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/receive/DeviceLoginResponseLength25.java
@@ -0,0 +1,31 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model.receive;
+
+import com.ifish.socket.model.HeadModel;
+import java.io.Serializable;
+
+/**
+ * 服务器回复插座的登录请求25字节(15字节头+8字节时间+2字节)
+ *
+ * @author guogw
+ *
+ */
+public class DeviceLoginResponseLength25 extends HeadModel implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ //系统时间
+ private byte[] sysTime = new byte[8];
+
+ public byte[] getSysTime() {
+ return sysTime;
+ }
+
+ public void setSysTime(byte[] sysTime) {
+ this.sysTime = sysTime;
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/model/receive/ServerHeartbeatLength17.java b/src/main/java/com/ifish/socket/model/receive/ServerHeartbeatLength17.java
new file mode 100644
index 0000000..32c19d4
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/receive/ServerHeartbeatLength17.java
@@ -0,0 +1,21 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model.receive;
+
+import com.ifish.socket.model.HeadModel;
+import java.io.Serializable;
+
+/**
+ * 服务器响应心跳17字节(15字节头+2校验码)
+ *
+ * @author guogw
+ *
+ */
+public class ServerHeartbeatLength17 extends HeadModel implements Serializable {
+
+ private static final long serialVersionUID = 8470317692571925603L;
+
+}
diff --git a/src/main/java/com/ifish/socket/model/send/APPLoginContextLength25.java b/src/main/java/com/ifish/socket/model/send/APPLoginContextLength25.java
new file mode 100644
index 0000000..1a05d53
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/send/APPLoginContextLength25.java
@@ -0,0 +1,30 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model.send;
+
+import com.ifish.socket.model.HeadModel;
+import java.io.Serializable;
+
+/**
+ * 手机登录请求25字节(17字节头+8字节登陆信息)
+ *
+ * @author guogw
+ *
+ */
+public class APPLoginContextLength25 extends HeadModel implements Serializable {
+
+ private static final long serialVersionUID = 5899193914651159511L;
+ //时间
+ private long longtime;
+
+ public long getLongtime() {
+ return longtime;
+ }
+
+ public void setLongtime(long longtime) {
+ this.longtime = longtime;
+ }
+}
diff --git a/src/main/java/com/ifish/socket/model/send/DeviceLoginContextLength24.java b/src/main/java/com/ifish/socket/model/send/DeviceLoginContextLength24.java
new file mode 100644
index 0000000..8adec41
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/send/DeviceLoginContextLength24.java
@@ -0,0 +1,61 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model.send;
+
+import com.ifish.socket.model.HeadModel;
+import java.io.Serializable;
+
+/**
+ * 设备登录服务器(24字节=17+7字节登陆信息)
+ *
+ * @author guogw
+ *
+ */
+public class DeviceLoginContextLength24 extends HeadModel implements Serializable {
+
+ private static final long serialVersionUID = 5329299292101065390L;
+ //厂商
+ private byte vendor;
+ //硬件型号
+ private byte hardware_type;
+ //版本
+ private byte version;
+ //登陆IP
+ private byte[] login_ip = new byte[4];
+
+ public byte getVendor() {
+ return vendor;
+ }
+
+ public void setVendor(byte vendor) {
+ this.vendor = vendor;
+ }
+
+ public byte getHardware_type() {
+ return hardware_type;
+ }
+
+ public void setHardware_type(byte hardware_type) {
+ this.hardware_type = hardware_type;
+ }
+
+ public byte getVersion() {
+ return version;
+ }
+
+ public void setVersion(byte version) {
+ this.version = version;
+ }
+
+ public byte[] getLogin_ip() {
+ return login_ip;
+ }
+
+ public void setLogin_ip(byte[] login_ip) {
+ this.login_ip = login_ip;
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/model/send/ModelVersionLength22.java b/src/main/java/com/ifish/socket/model/send/ModelVersionLength22.java
new file mode 100644
index 0000000..d21c083
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/send/ModelVersionLength22.java
@@ -0,0 +1,60 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model.send;
+
+import com.ifish.socket.model.HeadModel;
+import java.io.Serializable;
+
+/**
+ * 模块版本号,日期
+ *
+ * @author Administrator
+ */
+public class ModelVersionLength22 extends HeadModel implements Serializable {
+
+ private static final long serialVersionUID = -6712376303551767331L;
+ //版本
+ private byte version;
+ //年
+ private short year;
+ //月
+ private byte month;
+ //日
+ private byte day;
+
+ public byte getVersion() {
+ return version;
+ }
+
+ public void setVersion(byte version) {
+ this.version = version;
+ }
+
+ public short getYear() {
+ return year;
+ }
+
+ public void setYear(short year) {
+ this.year = year;
+ }
+
+ public byte getMonth() {
+ return month;
+ }
+
+ public void setMonth(byte month) {
+ this.month = month;
+ }
+
+ public byte getDay() {
+ return day;
+ }
+
+ public void setDay(byte day) {
+ this.day = day;
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/model/send/ModelVersionLength38.java b/src/main/java/com/ifish/socket/model/send/ModelVersionLength38.java
new file mode 100644
index 0000000..a4fe84d
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/send/ModelVersionLength38.java
@@ -0,0 +1,111 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model.send;
+
+import com.ifish.socket.model.HeadModel;
+import java.io.Serializable;
+
+/**
+ * 模块版本号,日期,38字节(17字节头+21字节)
+ *
+ * @author guogw
+ *
+ */
+public class ModelVersionLength38 extends HeadModel implements Serializable {
+
+ private static final long serialVersionUID = -6712376303551767331L;
+ //版本
+ private byte version;
+ //年
+ private short year;
+ //月
+ private byte month;
+ //日
+ private byte day;
+ //MCU启动次数
+ private int number1;
+ //模块启动次数
+ private int number2;
+ //连接路由器次数
+ private int number3;
+ //成功连接服务器次数
+ private int number4;
+ //尝试连接服务器次数
+ private int number5;
+
+ public byte getVersion() {
+ return version;
+ }
+
+ public void setVersion(byte version) {
+ this.version = version;
+ }
+
+ public short getYear() {
+ return year;
+ }
+
+ public void setYear(short year) {
+ this.year = year;
+ }
+
+ public byte getMonth() {
+ return month;
+ }
+
+ public void setMonth(byte month) {
+ this.month = month;
+ }
+
+ public byte getDay() {
+ return day;
+ }
+
+ public void setDay(byte day) {
+ this.day = day;
+ }
+
+ public int getNumber1() {
+ return number1;
+ }
+
+ public void setNumber1(int number1) {
+ this.number1 = number1;
+ }
+
+ public int getNumber2() {
+ return number2;
+ }
+
+ public void setNumber2(int number2) {
+ this.number2 = number2;
+ }
+
+ public int getNumber3() {
+ return number3;
+ }
+
+ public void setNumber3(int number3) {
+ this.number3 = number3;
+ }
+
+ public int getNumber4() {
+ return number4;
+ }
+
+ public void setNumber4(int number4) {
+ this.number4 = number4;
+ }
+
+ public int getNumber5() {
+ return number5;
+ }
+
+ public void setNumber5(int number5) {
+ this.number5 = number5;
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/model/send/TemperatureAlarmLength22.java b/src/main/java/com/ifish/socket/model/send/TemperatureAlarmLength22.java
new file mode 100644
index 0000000..569b57c
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/send/TemperatureAlarmLength22.java
@@ -0,0 +1,51 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model.send;
+
+import com.ifish.socket.model.HeadModel;
+import java.io.Serializable;
+
+/**
+ * 温度报警工作模式和温度指令22字节(17字节头+5字节)
+ *
+ * @author guogw
+ *
+ */
+public class TemperatureAlarmLength22 extends HeadModel implements Serializable {
+
+ private static final long serialVersionUID = -6712376303551767331L;
+ //报警温度类型,0是低温报警,1是高温报警
+ private byte warn_type;
+ //当前设备温度
+ private short wendu;
+ //报警温度
+ private short warn_wendu;
+
+ public byte getWarn_type() {
+ return warn_type;
+ }
+
+ public void setWarn_type(byte warn_type) {
+ this.warn_type = warn_type;
+ }
+
+ public short getWendu() {
+ return wendu;
+ }
+
+ public void setWendu(short wendu) {
+ this.wendu = wendu;
+ }
+
+ public short getWarn_wendu() {
+ return warn_wendu;
+ }
+
+ public void setWarn_wendu(short warn_wendu) {
+ this.warn_wendu = warn_wendu;
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/model/send/TemperatureSwitchLength22.java b/src/main/java/com/ifish/socket/model/send/TemperatureSwitchLength22.java
new file mode 100644
index 0000000..aad3aa2
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/send/TemperatureSwitchLength22.java
@@ -0,0 +1,51 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model.send;
+
+import com.ifish.socket.model.HeadModel;
+import java.io.Serializable;
+
+/**
+ * 设置报警温度开关指令22字节(17字节头+5字节)
+ *
+ * @author guogw
+ *
+ */
+public class TemperatureSwitchLength22 extends HeadModel implements Serializable {
+
+ private static final long serialVersionUID = -6712376303551767331L;
+ //开启关闭报警,00关,01开,02设置温度
+ private byte onoff;
+ //报警温度
+ private short low_wendu;
+ //报警温度
+ private short hight_wendu;
+
+ public byte getOnoff() {
+ return onoff;
+ }
+
+ public void setOnoff(byte onoff) {
+ this.onoff = onoff;
+ }
+
+ public short getLow_wendu() {
+ return low_wendu;
+ }
+
+ public void setLow_wendu(short low_wendu) {
+ this.low_wendu = low_wendu;
+ }
+
+ public short getHight_wendu() {
+ return hight_wendu;
+ }
+
+ public void setHight_wendu(short hight_wendu) {
+ this.hight_wendu = hight_wendu;
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/model/send/UpgradeVersionLength78.java b/src/main/java/com/ifish/socket/model/send/UpgradeVersionLength78.java
new file mode 100644
index 0000000..cf076d4
--- /dev/null
+++ b/src/main/java/com/ifish/socket/model/send/UpgradeVersionLength78.java
@@ -0,0 +1,41 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.model.send;
+
+import com.ifish.socket.model.HeadModel;
+import java.io.Serializable;
+
+/**
+ * 升级命令78字节(17字节头+61字节)
+ *
+ * @author guogw
+ *
+ */
+public class UpgradeVersionLength78 extends HeadModel implements Serializable {
+
+ private static final long serialVersionUID = 3696291654504951296L;
+ //版本
+ private byte version;
+ //地址
+ private byte[] address = new byte[60];
+
+ public byte getVersion() {
+ return version;
+ }
+
+ public void setVersion(byte version) {
+ this.version = version;
+ }
+
+ public byte[] getAddress() {
+ return address;
+ }
+
+ public void setAddress(byte[] address) {
+ this.address = address;
+ }
+
+}
diff --git a/src/main/java/com/ifish/socket/webService/MyService.java b/src/main/java/com/ifish/socket/webService/MyService.java
new file mode 100644
index 0000000..50dd40f
--- /dev/null
+++ b/src/main/java/com/ifish/socket/webService/MyService.java
@@ -0,0 +1,54 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.webService;
+
+import com.ifish.socket.config.SomeServer;
+import com.ifish.socket.model.OrderModel;
+import com.ifish.socket.model.send.UpgradeVersionLength78;
+import com.ifish.util.ByteUtil;
+import javax.jws.WebService;
+import org.apache.mina.core.session.IoSession;
+
+/**
+ *
+ * @author Administrator
+ */
+@WebService
+public class MyService {
+
+ //查询设备是否在线
+ public boolean deviceIsOnline(String macAddress) {
+ if (macAddress != null && macAddress.length() > 0) {
+ IoSession session = SomeServer.sessions_cz.get(macAddress);
+ if (session != null) {
+ if (session.getRemoteAddress() != null) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ //查询在线设备数量
+ public Integer getLineDeviceNumber() {
+ return SomeServer.sessions_cz.size();
+ }
+
+ //在线升级
+ public boolean onlineUpgrade(String macAddress, Integer upgradeVersion) {
+ if (macAddress != null && macAddress.length() > 0 && upgradeVersion != null) {
+ IoSession session = SomeServer.sessions_cz.get(macAddress);
+ if (session != null) {
+ if (session.getRemoteAddress() != null) {
+ UpgradeVersionLength78 model = OrderModel.UpgradeVersionLength78(ByteUtil.hexStringToBytes2(macAddress), upgradeVersion);
+ session.write(model);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/ifish/socket/webService/ServiceBean.java b/src/main/java/com/ifish/socket/webService/ServiceBean.java
new file mode 100644
index 0000000..d0b20d4
--- /dev/null
+++ b/src/main/java/com/ifish/socket/webService/ServiceBean.java
@@ -0,0 +1,19 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.socket.webService;
+
+import javax.xml.ws.Endpoint;
+
+/**
+ *
+ * @author Administrator
+ */
+public class ServiceBean {
+
+ public ServiceBean() {
+ Endpoint.publish("http://localhost:9001/Service/webService", new MyService());
+ }
+}
diff --git a/src/main/java/com/ifish/util/ByteUtil.java b/src/main/java/com/ifish/util/ByteUtil.java
new file mode 100644
index 0000000..76f63c9
--- /dev/null
+++ b/src/main/java/com/ifish/util/ByteUtil.java
@@ -0,0 +1,196 @@
+package com.ifish.util;
+
+import com.ifish.socket.model.DeviceResponseLength99;
+import java.util.Calendar;
+
+import org.apache.mina.core.buffer.IoBuffer;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class ByteUtil {
+
+ /**
+ * 将IoBuffer转换成byte
+ *
+ * @param str
+ */
+ public static byte[] ioBufferToByte(IoBuffer ioBuffer) {
+ byte[] b = new byte[ioBuffer.limit()];
+ ioBuffer.get(b, 0, b.length);
+ return b;
+ }
+
+ /**
+ * 将byte[]转换成IoBuffer
+ *
+ * @param str
+ */
+ public static IoBuffer byteToIoBuffer(byte[] bt, int length) {
+ IoBuffer ioBuffer = IoBuffer.allocate(100).setAutoExpand(true);
+ //ioBuffer.order(ByteOrder.LITTLE_ENDIAN);// 修改此缓冲区的字节顺大端模式
+ ioBuffer.put(bt, 0, length);
+ ioBuffer.flip();
+ return ioBuffer;
+ }
+
+ /**
+ * 16进制字节数组转16进制字符
+ *
+ * @param hexString
+ * @return byte[]
+ */
+ public static String bytesToHexString(byte[] src) {
+ StringBuilder stringBuilder = new StringBuilder();
+ if (src == null || src.length <= 0) {
+ return null;
+ }
+ for (int i = 0; i < src.length; i++) {
+ int v = src[i] & 0xFF;
+ String hv = Integer.toHexString(v);
+ if (hv.length() < 2) {
+ stringBuilder.append(0);
+ }
+ stringBuilder.append(hv);
+ }
+ return stringBuilder.toString();
+ }
+
+ /**
+ * 16进制字符串转换成字节数组(带空格)
+ *
+ * @param hexString
+ * @return byte[]
+ */
+ public static byte[] hexStringToBytes(String hexString) {
+ hexString = hexString.toLowerCase();
+ String[] hexStrings = hexString.split(" ");
+ byte[] bytes = new byte[hexStrings.length];
+ for (int i = 0; i < hexStrings.length; i++) {
+ char[] hexChars = hexStrings[i].toCharArray();
+ bytes[i] = (byte) (charToByte(hexChars[0]) << 4 | charToByte(hexChars[1]));
+ }
+ return bytes;
+ }
+
+ private static byte charToByte(char c) {
+ return (byte) "0123456789abcdef".indexOf(c);
+ }
+
+ /**
+ * 16进制字符串转换成字节数组(不带空格)
+ *
+ * @param hexString
+ * @return byte[]
+ */
+ public static byte[] hexStringToBytes2(String hex) {
+ hex = hex.toLowerCase();
+ int len = (hex.length() / 2);
+ byte[] result = new byte[len];
+ char[] achar = hex.toCharArray();
+ for (int i = 0; i < len; i++) {
+ int pos = i * 2;
+ result[i] = (byte) (charToByte(achar[pos]) << 4 | charToByte(achar[pos + 1]));
+ }
+ return result;
+ }
+
+ /**
+ * 把byte 转化为两位十六进制数
+ *
+ * @param b
+ * @return
+ */
+ public static String toHex(byte b) {
+ String result = Integer.toHexString(b & 0xFF);
+ if (result.length() == 1) {
+ result = '0' + result;
+ }
+ return result;
+ }
+
+ /**
+ * 当前16进制时间
+ *
+ * @return
+ */
+ public static byte[] hexSysTime() {
+ Calendar calendar = Calendar.getInstance();
+ String hexYear = String.format("%04x", calendar.get(Calendar.YEAR));
+ String hexMonth = String.format("%02x", (calendar.get(Calendar.MONTH) + 1));
+ String hexDate = String.format("%02x", calendar.get(Calendar.DATE));
+ String hexHours = String.format("%02x", calendar.get(Calendar.HOUR_OF_DAY));
+ String hexMinutes = String.format("%02x", calendar.get(Calendar.MINUTE));
+ String hexSeconds = String.format("%02x", calendar.get(Calendar.SECOND));
+ int hexDay = calendar.get(Calendar.DAY_OF_WEEK);
+ String dayOfWeek = String.format("%02x", hexDay == 1 ? 7 : hexDay - 1);
+ byte[] sysTime = hexStringToBytes2(hexYear + hexMonth + hexDate + hexHours + hexMinutes + hexSeconds + dayOfWeek);
+ return sysTime;
+ }
+
+ /**
+ * 将byte定时器转换成String
+ *
+ * @param str
+ */
+ public static String BytesToTimer(byte[] bys) {
+ StringBuilder s = new StringBuilder();
+ for (int i = 0; i < bys.length; i++) {
+ if (i == 1) {
+ s.append(String.format("%02d", (int) bys[i]) + "-");
+ } else if (i == 3) {
+ s.append(String.format("%02d", (int) bys[i]));
+ } else {
+ s.append(String.format("%02d", (int) bys[i]) + ":");
+ }
+ }
+ return s.toString();
+ }
+
+ /**
+ * 设备信息
+ *
+ * @return
+ */
+ public static String formatDeviceInfo(DeviceResponseLength99 model) {
+ String macAddress = ByteUtil.bytesToHexString(model.getSrc());
+ String wendu = (float) model.getWendu() / 10f + "℃";
+ String low_wendu = (float) model.getLow_wendu() / 10f + "℃";
+ String height_wendu = (float) model.getHigh_wendu() / 10f + "℃";
+ String warn_onoff = String.valueOf(model.getWarn_onoff());
+ String onff1 = String.valueOf(model.getOnoff1());
+ String onff2 = String.valueOf(model.getOnoff2());
+ String onff3 = String.valueOf(model.getOnoff3());
+ String timer_time1 = BytesToTimer(model.getTimer_time1());
+ String timer_time2 = BytesToTimer(model.getTimer_time2());
+ String timer_time3 = BytesToTimer(model.getTimer_time3());
+ String timer_time4 = BytesToTimer(model.getTimer_time4());
+ String timer_time5 = BytesToTimer(model.getTimer_time5());
+ String timer_time6 = BytesToTimer(model.getTimer_time6());
+ String timer_time7 = BytesToTimer(model.getTimer_time7());
+ String timer_time8 = BytesToTimer(model.getTimer_time8());
+ String timer_time9 = BytesToTimer(model.getTimer_time9());
+ JSONObject json = new JSONObject();
+ try {
+ json.put("macAddress", macAddress);
+ json.put("wendu", wendu);
+ json.put("low_wendu", low_wendu);
+ json.put("height_wendu", height_wendu);
+ json.put("warn_onoff", warn_onoff);
+ json.put("onff1", onff1);
+ json.put("onff2", onff2);
+ json.put("onff3", onff3);
+ json.put("timer_time1", timer_time1);
+ json.put("timer_time2", timer_time2);
+ json.put("timer_time3", timer_time3);
+ json.put("timer_time4", timer_time4);
+ json.put("timer_time5", timer_time5);
+ json.put("timer_time6", timer_time6);
+ json.put("timer_time7", timer_time7);
+ json.put("timer_time8", timer_time8);
+ json.put("timer_time9", timer_time9);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return json.toString();
+ }
+}
diff --git a/src/main/java/com/ifish/util/IfishFilePath.java b/src/main/java/com/ifish/util/IfishFilePath.java
new file mode 100644
index 0000000..65f72ed
--- /dev/null
+++ b/src/main/java/com/ifish/util/IfishFilePath.java
@@ -0,0 +1,113 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.util;
+
+import com.ifish.enums.SubDirectoryEnum;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.util.Properties;
+
+/**
+ *
+ * @author Administrator
+ */
+public class IfishFilePath {
+
+ //头像地址
+ public static String path_img;
+ /**
+ * 图片头地址
+ */
+ public static String link_img_head;
+ //商家图片地址
+ public static String path_shops;
+ //商品介绍图片
+ public static String path_commodity;
+ //微信分享页面
+ public static String path_share_html;
+ //微信分享页图片
+ public static String path_share_img;
+ //看护报告页面
+ public static String path_look_html;
+ //看护报告图片
+ public static String path_look_img;
+ //html名字
+ public static String html_name;
+ //图片上传格式
+ public static String check_style;
+ //云信爱鱼奇官方帐号
+ public static String ifish_account;
+ //IM官方手机号
+ public static String netease_phone;
+ //直播间封面
+ public static String path_room_img;
+ //FastDFS商家视频上传URL访问路径(本地和测试环境)
+ public static String fastDFS_url_local;
+ //FastDFS商家视频上传URL访问路径(正式环境)
+ public static String fastDFS_url_app;
+ //开发模式
+ public static boolean devModel;
+ //本机IP
+ public static String ifiship;
+ //本机端口
+ public static int ifishport;
+
+ static {
+ Properties prop = new Properties();
+ InputStream in = IfishFilePath.class.getResourceAsStream("/property.properties");
+ try {
+ prop.load(in);
+ //利用反射机制给属性赋值
+ Field[] fields = IfishFilePath.class.getDeclaredFields();
+ for (Field field : fields) {
+ String name = field.getName();
+ //获取property.properties的值
+ String value = prop.getProperty(name).trim();
+ //判断这个值希望塞入的变量类型,并进行转换
+ Object value1 = getValue(value, field);
+ //转换完成后塞入此变量
+ field.set(IfishFilePath.class, value1);
+
+ }
+ in.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 验证图片格式
+ */
+ public static String checkImgName(String fileName) {
+ //对格式进行验证
+ int index = fileName.lastIndexOf(".");
+ String extEndName = fileName.substring(++index, fileName.length());
+ if (check_style.indexOf(extEndName.toUpperCase()) == -1) {
+ return null;
+ }
+ //返回格式.png
+ return "." + extEndName;
+ }
+
+ /**
+ * 获取图片链接地址
+ *
+ * @param type
+ * @return
+ */
+ public static String getPath(SubDirectoryEnum pictureEnum, String fileName) {
+ return link_img_head + pictureEnum.getKey() + fileName;
+ }
+
+ private static Object getValue(String value, Field field) {
+ if (field.getType().equals(int.class)) {
+ return Integer.valueOf(value);
+ } else if (field.getType().equals(boolean.class)) {
+ return Boolean.valueOf(value);
+ }
+ return value;
+ }
+}
diff --git a/src/main/java/com/ifish/util/IfishUtil.java b/src/main/java/com/ifish/util/IfishUtil.java
new file mode 100644
index 0000000..3ea006d
--- /dev/null
+++ b/src/main/java/com/ifish/util/IfishUtil.java
@@ -0,0 +1,454 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.JavaType;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ *
+ * @author Administrator
+ */
+public class IfishUtil {
+
+ private static final String formatDate = "yyyy-MM-dd HH:mm:ss";
+
+ private static final String formatDate3 = "MM-dd HH:mm";
+
+ private static final String formatDate2 = "yyyy-MM-dd HH:mm";
+
+ private static final String formatDate1 = "yyyy-MM-dd";
+
+ /**
+ * 测试缓存时间:一分钟;单位:秒
+ */
+ public static final int CacheTime_Test_SECONDS = 60;
+ /**
+ * 缓存时间:一秒;单位:秒
+ */
+ public static final int CacheTime_SECONDS = 1;
+ /**
+ * 缓存时间:一分钟;单位:分
+ */
+ public static final int CacheTime_MINUTES = 1;
+ /**
+ * 缓存时间:一小时;单位:小时
+ */
+ public static final int CacheTime_HOURS = 1;
+ /**
+ * 缓存时间:一天;单位:天
+ */
+ public static final int CacheTime_DAYS = 1;
+
+ /**
+ * Object转Json
+ */
+ public static String ObjectToJson(Object value) {
+ try {
+ if (value == null) {
+ return null;
+ }
+ ObjectMapper mapper = new ObjectMapper();
+ String js = mapper.writeValueAsString(value);
+ return js;
+ } catch (Exception ex) {
+ System.out.println("【异常信息】 >>> " + ex.toString());
+ return "Error";
+ }
+ }
+
+ /**
+ * Json转Object(List)
+ *
+ * @param json 需要转换的JSON字符串
+ * @param bean JavaBean,
+ * @return 拿到结果需要强转一次,因为你拿到的是Object, 例如这样调用和强转: List<School> lst
+ * =(List<School>)StringUtil.JsonToObjectList(value, School.class);
+ */
+ public static Object JsonToList(String json, Class> bean) throws Exception {
+ ObjectMapper mapper = new ObjectMapper();
+ JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, bean);
+ return mapper.readValue(json, javaType);
+ }
+
+ /**
+ * Json转Object(JavaBean)
+ *
+ * @param json 需要转换的JSON字符串
+ * @param bean JavaBean,
+ * @return 拿到结果需要强转一次,因为你拿到的是Object, 例如这样调用和强转: School lst
+ * =(School)StringUtil.JsonToObjectList(value, School.class);
+ */
+ public static Object JsonToBean(String json, Class> bean) throws Exception {
+ ObjectMapper mapper = new ObjectMapper();
+ JavaType javaType = mapper.getTypeFactory().uncheckedSimpleType(bean);
+ return mapper.readValue(json, javaType);
+ }
+
+ /**
+ * 将json格式的字符串解析成Map对象
+ */
+ public static Map> JsonToMap(String json) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ Map> maps = mapper.readValue(json, Map.class);
+ return maps;
+ } catch (Exception e) {
+ System.out.println("【异常信息】 >>> " + e.toString());
+ return null;
+ }
+ }
+
+ public static Map JsonToMapContainMap(String json) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ Map maps = mapper.readValue(json, Map.class);
+ return maps;
+ } catch (Exception e) {
+ System.out.println("【异常信息】 >>> " + e.toString());
+ return null;
+ }
+ }
+
+ public static Map JsonToRealMap(String json) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ Map maps = mapper.readValue(json, Map.class);
+ return maps;
+ } catch (Exception e) {
+ System.out.println("【异常信息】 >>> " + e.toString());
+ return null;
+ }
+ }
+
+
+ //返回时分秒的时间字符串
+ public static String TimestampToStringAndSecond(Object timestamp) {
+ DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ try {
+ return (format.format(timestamp));
+ } catch (Exception e) {
+ System.out.println("【isGaokaoYearExpire 异常】:" + e);
+ return "";
+ }
+ }
+
+ //返回时分秒的时间字符串
+ public static String TimestampToStringAndSecond(Object timestamp, String geshi) {
+ DateFormat format = new SimpleDateFormat(geshi);
+ try {
+ return (format.format(timestamp));
+ } catch (Exception e) {
+ System.out.println("【isGaokaoYearExpire 异常】:" + e);
+ return "";
+ }
+ }
+
+ /**
+ * 返回当前日期yyyy-MM-dd
+ *
+ * @return
+ * @throws ParseException
+ */
+ public static Date getCurDate() {
+ DateFormat df = DateFormat.getDateInstance();
+ try {
+ return df.parse(df.format(new Date()));
+ } catch (ParseException e) {
+ }
+ return null;
+ }
+
+ /**
+ * 格式化日期yyyy-MM-dd HH:mm:ss
+ *
+ * @param date
+ * @return
+ */
+ public static String format(Date date) {
+ SimpleDateFormat format = new SimpleDateFormat(formatDate);
+ return format.format(date);
+ }
+
+ /**
+ * 格式化日期
+ *
+ * @param date
+ * @return
+ */
+ public static String format1(Date date) {
+ SimpleDateFormat format = new SimpleDateFormat(formatDate1);
+ return format.format(date);
+ }
+
+ /**
+ * 格式化日期
+ *
+ * @param date
+ * @return
+ */
+ public static String format2(Date date) {
+ SimpleDateFormat format = new SimpleDateFormat(formatDate2);
+ return format.format(date);
+ }
+
+ /**
+ * 格式化日期
+ *
+ * @param date
+ * @return
+ */
+ public static String format3(Date date) {
+ SimpleDateFormat format = new SimpleDateFormat(formatDate3);
+ return format.format(date);
+ }
+
+ /**
+ * 字符串转换成日期
+ *
+ * @param str
+ * @return date
+ */
+ public static Date StrToDate(String str) {
+ SimpleDateFormat format = new SimpleDateFormat(formatDate1);
+ Date date = null;
+ try {
+ date = format.parse(str);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ return date;
+ }
+
+ /**
+ * 随机生成字母与数字组合
+ *
+ * @param length
+ * @return
+ */
+ public static String getCharAndNumr(int length) {
+ String val = "";
+ Random random = new Random();
+ for (int i = 0; i < length; i++) {
+ // 输出字母还是数字
+ String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
+ // 字符串
+ if ("char".equalsIgnoreCase(charOrNum)) {
+ // 取得大写字母还是小写字母
+ int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;
+ val += (char) (choice + random.nextInt(26));
+ // 数字
+ } else if ("num".equalsIgnoreCase(charOrNum)) {
+ val += String.valueOf(random.nextInt(10));
+ }
+ }
+ return val;
+ }
+
+ /**
+ * 返回json数据
+ *
+ * @param str
+ * @return
+ */
+ public static Map returnJson(String key, Object value) {
+ Map map = new HashMap();
+ map.put("result", key);
+ if (value.equals("")) {
+ map.put("data", null);
+ } else {
+ map.put("data", value);
+ }
+ return map;
+ }
+
+ /**
+ * 返回json数据
+ *
+ * @param str
+ * @return
+ */
+ public static Map toJson(String key, Object value) {
+ Map map = new HashMap();
+ map.put("result", key);
+ if (value.equals("")) {
+ map.put("data", null);
+ } else {
+ map.put("data", value);
+ }
+ return map;
+ }
+
+ /**
+ * 上传图片文件
+ *
+ * @param fileUpload
+ * @param path
+ * @return
+ */
+ public static String uploadFile(MultipartFile fileUpload, String path) {
+ //根据时间得文件名
+ Calendar calendar = Calendar.getInstance();
+ String fileName = String.valueOf(calendar.getTimeInMillis());
+ //保存文件
+ if (fileUpload == null) {
+ return "base/default.png";
+ }
+ if (!fileUpload.isEmpty()) {
+ try {
+ if (!fileUpload.getOriginalFilename().equals("")) {
+ File picFile = new File(path, fileName + ".png");
+ //不存在则创建
+ if (!picFile.exists()) {
+ picFile.mkdirs();
+ }
+ //保存
+ fileUpload.transferTo(picFile);
+ }
+ return "share/" + fileName + ".png";
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return "";
+ }
+
+ /**
+ * 生成微信分享页面
+ *
+ * @param title
+ * @param base64
+ * @return
+ */
+ public static String getHtmlFile(String title, String pngName, String modelFile, String filePath) {
+ try {
+ if (pngName != null && !pngName.equals("")) {
+ //读取模板文件
+ FileInputStream fileinputstream = new FileInputStream(filePath + modelFile);
+ int lenght = fileinputstream.available();
+ byte bytes[] = new byte[lenght];
+ fileinputstream.read(bytes);
+ fileinputstream.close();
+ String templateContent = new String(bytes);
+ //替换掉模板中相应的地方
+ templateContent = templateContent.replaceAll("###title###", title);
+ templateContent = templateContent.replaceAll("###fileName###", pngName);
+ //根据时间得文件名
+ Calendar calendar = Calendar.getInstance();
+ String fileName = String.valueOf(calendar.getTimeInMillis());
+ fileName = fileName + ".html";
+ //建立文件输出流
+ FileOutputStream fileoutputstream = new FileOutputStream(filePath + fileName);
+ byte tag_bytes[] = templateContent.getBytes();
+ fileoutputstream.write(tag_bytes);
+ fileoutputstream.close();
+ return fileName;
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return "";
+ }
+
+ /**
+ * 随即区间整数
+ *
+ * @param min
+ * @param max
+ * @return
+ */
+ public static int getRandom(int min, int max) {
+ int r = new Random().nextInt(max - min);
+ return r + min;
+ }
+
+ /**
+ * URL 解码
+ *
+ * @return String
+ * @author lifq
+ * @date 2015-3-17 下午04:09:51
+ */
+ public static String getURLDecoderString(String str) {
+ String result = "";
+ if (null == str) {
+ return "";
+ }
+ try {
+ result = java.net.URLDecoder.decode(str, "GBK");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * URL 转码
+ *
+ * @return String
+ * @author lifq
+ * @date 2015-3-17 下午04:10:28
+ */
+ public static String getURLEncoderString(String str) {
+ String result = "";
+ if (null == str) {
+ return "";
+ }
+ try {
+ result = java.net.URLEncoder.encode(str, "GBK");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * 正则表达式截取字符串
+ *
+ * @param str
+ * @param regex
+ * @return
+ */
+ public static String regex(String str, String regex) {
+ Matcher matcher = Pattern.compile(regex).matcher(str);
+ if (matcher.find()) {
+ return matcher.group(0);
+ } else {
+ return "";
+ }
+ }
+
+ public static String regexToChinese(String str) {
+ String regex = "([\\u4e00-\\u9fa5]+)";
+ return regex(str, regex);
+ }
+
+ /**
+ * 验证当前系统是windows(本地,返回true),还是unix(服务器,返回false)
+ *
+ * @return
+ */
+ public static boolean IsWinOrUnix() {
+ String os = System.getProperty("os.name");//获取当前操作系统
+ return os.toLowerCase().startsWith("win");
+ }
+}
diff --git a/src/main/java/com/ifish/util/JdbcProperties.java b/src/main/java/com/ifish/util/JdbcProperties.java
new file mode 100644
index 0000000..9260ea9
--- /dev/null
+++ b/src/main/java/com/ifish/util/JdbcProperties.java
@@ -0,0 +1,61 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.util;
+
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.util.Properties;
+
+/**
+ *
+ * @author Administrator
+ */
+public class JdbcProperties {
+
+ public static String driverClassName;
+ public static String url;
+ public static String username;
+ public static String password;
+ public static boolean autoCommitOnClose;
+ public static int initialPoolSize;
+ public static int minPoolSize;
+ public static int maxPoolSize;
+ public static int acquireIncrement;
+ public static int checkoutTimeout;
+ public static int maxIdleTime;
+ public static int idleConnectionTestPeriod;
+
+ static {
+ Properties prop = new Properties();
+ InputStream in = IfishFilePath.class.getResourceAsStream("/jdbc.properties");
+ try {
+ prop.load(in);
+ //利用反射机制给属性赋值
+ Field[] fields = JdbcProperties.class.getDeclaredFields();
+ for (Field field : fields) {
+ String name = field.getName();
+ //获取property.properties的值
+ String value = prop.getProperty(name).trim();
+ //判断这个值希望塞入的变量类型,并进行转换
+ Object value1 = getValue(value, field);
+ //转换完成后塞入此变量
+ field.set(IfishFilePath.class, value1);
+ }
+ in.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static Object getValue(String value, Field field) {
+ if (field.getType().equals(int.class)) {
+ return Integer.valueOf(value);
+ } else if (field.getType().equals(boolean.class)) {
+ return Boolean.valueOf(value);
+ }
+ return value;
+ }
+}
diff --git a/src/main/java/com/ifish/util/RedisKey.java b/src/main/java/com/ifish/util/RedisKey.java
new file mode 100644
index 0000000..331f03a
--- /dev/null
+++ b/src/main/java/com/ifish/util/RedisKey.java
@@ -0,0 +1,78 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.ifish.util;
+
+/**
+ *
+ * @author Administrator
+ */
+public class RedisKey {
+
+ /**
+ * 用户缓存前缀
+ */
+ public static final String User_Key = "userE:";
+
+ /**
+ * 商家信息缓存前缀
+ */
+ public static final String ShopsInfo_Key = "shopsInfoE:";
+
+ /**
+ * 用户绑定设备缓存前缀
+ */
+ public static final String DeviceUser_Key = "deviceUserE:";
+
+ /**
+ * 设备绑定摄像头缓存前缀
+ */
+ public static final String DeviceCamera_key = "deviceCameraE:";
+
+ /**
+ * 设备详情缓存前缀
+ */
+ public static final String Device_key = "deviceE:";
+
+ /**
+ * 设备类型缓存前缀
+ */
+ public static final String HardWareType_key = "hardwaretypeE:";
+
+ /**
+ * 厂家列表缓存前缀
+ */
+ public static final String VenderList_key = "venderlistE:";
+
+ /**
+ * 用户和摄像头的绑定关系存前缀
+ */
+ public static final String CameraUser_key = "cameraUserE:";
+
+ /**
+ * 摄像头详情缓存前缀
+ */
+ public static final String Camera_key = "cameraE:";
+
+ /**
+ * 设备统计信息表缓存前缀
+ */
+ public static final String DeviceStatistic_key = "deviceStaticticsE:";
+
+ /**
+ * 直播间详情表缓存前缀
+ */
+ public static final String LiveRoom_key = "liveroomE:";
+
+ /**
+ * 直播间数量缓存前缀
+ */
+ public static final String LIVEROOM_COUNT_KEY = "liveroomcountE:";
+
+ /**
+ * 推送消息缓存前缀
+ */
+ public static final String PUSHLIST_KEY = "pushlistE:";
+}
diff --git a/src/main/resources/fdfs_client_ifish7.conf b/src/main/resources/fdfs_client_ifish7.conf
new file mode 100644
index 0000000..9661bfb
--- /dev/null
+++ b/src/main/resources/fdfs_client_ifish7.conf
@@ -0,0 +1,7 @@
+connect_timeout = 2
+network_timeout = 30
+charset = UTF-8
+http.tracker_http_port = 85
+http.anti_steal_token = no
+http.secret_key = FastDFS1234567890
+tracker_server = 120.55.190.56:22131
\ No newline at end of file
diff --git a/src/main/resources/fdfs_client_zhangxinyanv5.conf b/src/main/resources/fdfs_client_zhangxinyanv5.conf
new file mode 100644
index 0000000..6a88c9e
--- /dev/null
+++ b/src/main/resources/fdfs_client_zhangxinyanv5.conf
@@ -0,0 +1,8 @@
+connect_timeout = 2
+network_timeout = 30
+charset = UTF-8
+http.tracker_http_port = 8017
+http.anti_steal_token = no
+http.secret_key = FastDFS1234567890
+tracker_server = 139.196.24.156:22122
+
diff --git a/src/main/resources/jdbc.properties b/src/main/resources/jdbc.properties
new file mode 100644
index 0000000..1b38a52
--- /dev/null
+++ b/src/main/resources/jdbc.properties
@@ -0,0 +1,40 @@
+#c3p0.driverClassName=com.mysql.jdbc.Driver
+#c3p0.url=jdbc\:mysql\://localhost\:3306/myfishdbenglish?characterEncoding\=UTF-8
+#c3p0.username=ifish
+#c3p0.password=ifish7pwd
+#c3p0.autoCommitOnClose=true
+#c3p0.initialPoolSize=20
+#c3p0.minPoolSize=20
+#c3p0.maxPoolSize=50
+#c3p0.acquireIncrement=3
+
+#c3p0.checkoutTimeout=5000
+#c3p0.maxIdleTime=7200
+#c3p0.idleConnectionTestPeriod=18000
+#c3p0.maxIdleTimeExcessConnections=1800
+
+#c3p0.automaticTestTable=C3P0TestTable
+#c3p0.testConnectionOnCheckout=false
+#c3p0.testConnectionOnCheckin=false
+
+#\u8fd9\u91cc\u662f\u4e0a\u9762\u53d6\u6d88\u524d\u7f00\u7684\u5f15\u7528,\u5982\u679c\u4fee\u6539\uff0c\u8bf7\u4fee\u6539\u8fd9\u91cc
+driverClassName=com.mysql.jdbc.Driver
+url=jdbc\:mysql\://localhost\:3306/myfishdbenglish?characterEncoding\=UTF-8
+username=ifish
+password=ifish7pwd
+autoCommitOnClose=true
+initialPoolSize=20
+minPoolSize=20
+maxPoolSize=50
+acquireIncrement=3
+checkoutTimeout=5000
+maxIdleTime=7200
+idleConnectionTestPeriod=18000
+
+#org.hibernate.dialect.MySQLInnoDBDialect
+hibernate.dialect=org.hibernate.dialect.MySQLDialect
+hibernate.show_sql=false
+hibernate.format_sql=true
+hibernate.hbm2ddl.auto=false
+hibernate.jdbc.batch_size=50
+hibernate.query.substitutions=true 1,false 0
diff --git a/src/main/resources/property.properties b/src/main/resources/property.properties
new file mode 100644
index 0000000..6fa1e49
--- /dev/null
+++ b/src/main/resources/property.properties
@@ -0,0 +1,44 @@
+#\u5934\u50cf\u5b58\u50a8\u8def\u5f84
+path_img=/mydata/tmp/Img/app
+#\u5546\u5bb6\u8ba4\u8bc1\u56fe\u7247
+path_shops=/mydata/tmp/Img/shops
+#\u5546\u54c1\u4ecb\u7ecd\u56fe\u7247
+path_commodity=/mydata/tmp/Img/commodity
+#\u76f4\u64ad\u95f4\u5c01\u9762
+path_room_img=/mydata/tmp/Img/room
+#\u5fae\u4fe1\u5206\u4eab\u9875\u9762
+path_share_html=/mydata/tmp/html/
+#\u5fae\u4fe1\u5206\u4eab\u9875\u56fe\u7247
+path_share_img=/mydata/tmp/html/images/share
+#\u770b\u62a4\u62a5\u544a\u9875\u9762
+path_look_html=/mydata/tmp/look/
+#\u770b\u62a4\u62a5\u544a\u56fe\u7247
+path_look_img=/mydata/tmp/look/images/share
+#\u770b\u62a4\u62a5\u544a\u6a21\u7248html\u540d\u5b57
+html_name=index.html
+#\u4e91\u4fe1\u7231\u9c7c\u5947\u5b98\u65b9\u5e10\u53f7
+ifish_account=ifish
+#IM\u5b98\u65b9\u624b\u673a\u53f7
+netease_phone=18501773036
+#FastDFS\u6587\u4ef6URL\u8bbf\u95ee\u8def\u5f84(\u672c\u5730\u548c\u6d4b\u8bd5\u73af\u5883)
+fastDFS_url_local=https://app.zhangxinyanv5.top/
+#FastDFS\u6587\u4ef6URL\u8bbf\u95ee\u8def\u5f84(\u6b63\u5f0f\u73af\u5883)
+fastDFS_url_app=http://app.ifish7.com/
+#\u672c\u5730
+#link_img_head=http://192.168.61.128:81/
+#\u6d4b\u8bd5\u73af\u5883
+#link_img_head=https://app.zhangxinyanv5.top/
+#\u6b63\u5f0f\u73af\u5883
+link_img_head=https://app.ifish7.com/
+#\u56fe\u7247\u683c\u5f0f\u9a8c\u8bc1
+check_style=GIF,PNG,BMP,JPG,JPEG
+#\u662f\u5426\u5f00\u53d1\u6a21\u5f0f\uff0cfalse\u5219\u4ee3\u8868\u8981\u53d1\u5e03\u5230\u6d4b\u8bd5\u6216\u8005\u6b63\u5f0f\u73af\u5883\uff0c\u4f1a\u8fdb\u884c\u5168\u5c40\u5934\u90e8\u9a8c\u8bc1\uff0ctrue\u4ee3\u8868\u5728\u672c\u5730\u8fdb\u884c\u4ee3\u7801\u7f16\u5199\uff0c\u4e0d\u4f1a\u8fdb\u884c\u9a8c\u8bc1
+devModel=true
+#\u672c\u5730
+ifiship=192.168.199.129
+#\u6d4b\u8bd5\u4e91
+#ifiship=139.196.24.156
+#\u6b63\u5f0f\u4e91
+#ifiship=120.55.190.56
+#\u670d\u52a1\u5668\u7aef\u53e3
+ifishport=9956
\ No newline at end of file
diff --git a/src/main/webapp/META-INF/context.xml b/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..a800ff1
--- /dev/null
+++ b/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/src/main/webapp/WEB-INF/lib/fastdfs-client-java-1.25.jar b/src/main/webapp/WEB-INF/lib/fastdfs-client-java-1.25.jar
new file mode 100644
index 0000000000000000000000000000000000000000..74adb9294c5580275b3cd37fefcb9311db2073bf
GIT binary patch
literal 91061
zcma&N1C%Avk}h0bw#_bf*=Cnc*|u%lwyiGPwr$(Ct-tTwJM-Smdo%CPwRWCdDh;S2KvXrszodIZx{bMLH+%e5?17=5t9bc$^J_W5{Tum*xNcgnZw`P
z5q}%%|1KuQFD(WTR#2ps0^CbYj7v(;(9Xh1&`?fIOxMfPFEH&K+Ea^9jZjO_2tYy{
z6euU6Q}vLzwq}YmIfy%EQC6bjD%dmKGe$^+BTL-*Ax{aHhLM(1AeQ4xwsQCtAj8p}T|M27?1SG&?kb{=Jhx|JKRB{rZms^zW68y~%$J%Y-(G;(nK
z4>ibtvsgDh9ce!t5Re5X5D>wCQTtcV1oRw?Sea=JEcF~5CRHt5GZ*c=O}cI9)GKeq
zjiUldI*#-Q#JeKkl4)LvGE`NQVUuC|0$m&5NGdzmHZKM-&e)~PkpECDFvG>d3=Q!^
zkquyKFpe<927+e7kOYy$CJL-E|4tBid${AaA~@mNu3AD4W&J2G;4zuXbU5l@GBKX2
znCiHHF$0RYfnd9O(8u~33z+t}U49XO0(CKSXl8vjy%)CXIxxC7qU-Ya=xjlR*l3xK
zV8mTGie-I1_wVO?RzkqP(G^OA5GTL4!1vsYfUp~g3h5}BtMAJF>|gU#$jHa%&Kr*@
zi!`w2F4K>;aOjJYLm2940sV!xZGg{RRX4=LemK}{tB%35+nX@vDV||d9(jGTc1=0h
zpS{GgJ>UDBS*6a2zK37k+pJ@pz^~SB5u0=yiT%A|YXc~zb!&$d%7r$DRDTtnwyfQDCwPGH@Xd=d5u~D{iZ$a3o)YE|kZ{E(&%oxG|i{HtEk*DToy4ca2oCQBK2Xmq%
zwJP4I>Mo${xXQxH%1U9k>SSlgH5w-n+bu63L;hAYn3HQ%g=T`&Bds*FMg93yRbLZX
z;z6x_qybqDXSbq_rkpNgDqXtK7;yM2#9d6jinvWEV{nan&X_RhsSHa6#&cAYHECRW
zWjk(H=bVBf0$*SrUuK)>|rqFLV#EYD0ae
z1OZp!jPCngrH&!4NTK>x(M%LIPyeo4ZLILGW!?{-FMe4UXL}`1yw%MjzvZ-X=cno-
zod=_E3^LWlWZ9loL;CB+ULi)DND}`gcq$~^vBCOU#SLh(_kbw=NhMIdLZ)&5Qc)dS
zlSoR|>E(duw;P-f;!9N6w;PQ`B9Tt^FhHbHv5@SXNw;farO_N`$+*Pe!5*b2PPaA!okT>bu%Qa
z{S<}y>{cw-F#{GM&0E5Tnd7ySCcD!;Wh98q_e>cF
zaiFDwle#aBtmbPh`K2{*_+M9Fn}n9IXENo}rK;+krF5YsL%h>E%Q7%ht&QrGxSz_c
z)Y~7>o@bn(5q#B5_*|Lf-82As>+Pv1)DwEI4UvnX5b%=&1-R*vm)Wl?S84H=-cg$>
z`ZUL2Dr+4v_8r!9EpW&ClofQ*>uO(NT|kyxqpKhZsEF`Uy+~#B(tX@NOh&q|Ks5=!
z#}uYeY(vJdZnjWv0yox@0zV$Vz`l+cTnTE8tPMQ~kpdFM8jJ>55=zS4?gqJQ@m2Qi
zHT%(T4rTUD6P7fE=9GTh2YO^(qQl`lIyj}B
zF!-4Mh?U>mpkQ^Pp$L)E5*e$Z=!BgI-%f?B#n)EEFht>AKVz%AU5
zKFO#3kaU|@9f{#N*ds@9W>t9&4vpn$Y~ejWD!7By
z(2k?>;y>BT+=pzvg&)by%>i;;;V?zg6Gws8R8w|{-0F_6Y_kK-dl-MUGzLkz1AWpnRPOK3K{X5Q|yR9X(7$Lr<{;nd;SjNx~X=Jc)G!+Zt39_t)hf3$l-eN)8jb|0X=|GM42
z^FnfyhJ9^Ky=!8}d&8)r}0dx_m3<}Ke~$~$^ZOymXB_ZTVSQr3DDA-Pv@j0=Z$l@yR}r@4|ZHetK`
z5VcEWe}R+j@Z?NIj-CYl4cw9HA#9eqRWXnvPJw9
zhCv1R91ac6{Hhk}w*h^Rs&QGNX>_*qZbD245K_|}igY>&_TaEiCL;-f6m2(BO}s$6
zJ_kwtQo|{((==p}F=7GDoT~ic;DfQ6&GWS4Ijt(vFWqm7^>ou)Qr!t*wBJ%ttbc_`
z>*YUx)m2mPcX|V443=5UEtL(PKV|@$`AbgaaCOFZ=?meWCukz~k`9oj3Edq?uYfH}
zdM`_S&!B>?*F_B|XVx#*^edqj?4}lxRNg~38$33IvrcJTp*y#2ZrJtJ3<{{j4=Dr@
z!6XqBcZ?$6F*|?T41xzOPMwqIJz)3ErjQ~FioAjUO0QjFWt+pOZd8y%SpWr9|Tvzg85tYB`GN8%mufVoqL4oaX>oc2HMtg{YMu+AVES4uprqcRw3
z@>Zc4agR!;uhYdEk220LWOaN)Y%BlFez%Q2IvNKcVfR*;cYpJ~B=wS)GAGCU`Lfi9
zUtB}j5@U|^r)VwG{}TEL4i*lE~3!XNanm(57+`1#yR2%$Ho_j2$#2`M0ly9-@Xr`whw^BoOzU-MP
z15-OtUSQB%4jQ~?v8S!!RY8JrO6k=LGT!o>zW&a1VQcnhP&|{6|||!J&!Lph+wu+ktaOUfm_}e
z6!0CeTz9BM>Nw5;DRq2G+N94Y_ZOA%&GHOk^&bW8L9!4ti>7FMlNk-`qGL#hYkA`u
z<7^~d@6MpaUIBYn>%t~7mB}8f1CG+_Fg}yhlBSbA565<^2(Iw$H0yj&E)ev{ny$Rk
zO>Y=hW?3EcMqb4kXztRwk|eD|u8te_4{|5^XD(x+of4r!VqeN(w-P5sv@C(~feb4j
zIwS54{dW(J*XA`lO{L!@+kd|1y7oW6LH<3;{b&4#WwP?11r7wn|2Kdo`@hG3V%BB=
zGfN|RBRxYS`+tUkQOXt$C`On(>y~w5s+Jk@%tWe4q*6FUp=jg65{<|-mC&frl$Hrr
z>FLH2b)^lO9ouMV!r-_f9g$9`c(x?Mm`Hr&@ZPrIpJaSJw<4j(n_9_D6)C3=o!Q53
zQw|<%$6uUo*gg8VkOn`NLTrgy134Z-7l-JphRDD=p;<$6bt78b*ds-5Oc6EuA$2tn
z)e*h;3kGS4f4gITj!|24e;Xtk53i0VM{8KkCy5
zd8+k>`VW%^hBW4}HfW!ZpCg}fK{O)KsIfY{9$;58>xSA%3JwTc
zYHCv%CY(>`SH+T&*AS_Uq?MPDIv+Y2#DKPLj>xvOF{#Y7j|qCY&obbgGS8`ZiBKI4
zY;hz``e};weMsl0N)<@}T2q%2%nVFN$Vn7}G$BU03oNiYMdx=toC_ZHm`qT`p`FPw
z3zI6Wn-ZKtB;1uNW+R?pfm=^!?~MGdpZ2au$=1ca0NXnYu8z-eXJ+$qnUtx~d#m{2
z3Q-h8tohFthaIg>1K{G^3gQOQsp6#NaKztq>a1+mMX29`1M2L-R=Ftz8r<`&d!Y+%
z+T)J4Z-wW1>1+*>BD0vta%4XwluW7&rD+PA^yP5ShEZ?pw<#FBeUwB>J6vy)|wP=#*MD>Z4AZ(*~QZgI0!Zv4YB
zZjsfrPXFklnYeduA~(~?5bm=UhpW^m4wmb?!g(llM6;Q?6o#|a$_#3_Y7Bb!?%+j=
znZ8tOrz3-MO(GvjAFUgu;sIJ??YORx>9&g7er3Js=N)@hjGAd3D$3-m@GlO_XCF7F
zOs~khE7QZ(#fx(`f8XrY#F#%^8qw&88^HkNY?j5}_rn20I%@}h3emUq}{;{Ng0(skQ54S1Y;r0yEV)Y#o=E+2Q#AcDYuw^Y%@swNizUt9B#!uCJa2cL&J{U
z8MV}ajfe%UNRp-7MXv(s(1;}6*bFbk4ay}k39IM(VkwJmI|EtLn~*PE0}?4D;oL;R
zCtVwMBMdq$g8s0`nC_#)v--mK3xH(J;ol*L7*yexto62fOHt-^MReYKzH
zr5ra5s9bu~C$w(vfSg@78c?>|6z`A{Jk}P>d#sZN$vLEXuQUs>YG)#lo?V@OD5M>&9+a&g(uIWuf+l_u_QU9{Jcc&5M9I}lt
zk&@$(VPb54XoGYj{vzbRL|TEWB)d*2ayY+7MEQ=)TP5=|z9q9>7#37k7asP=lFPxE
z(S&$nbw4!*kNP~Tpd$inbMp6P?MXFJCr4rn&a*0(l>?rc15?|?Xh{huPD&58GI7TT%PGFZ(*Cbz5E4Y(`HA}Yo(viHdx1^^Mi`V1TlYad
zV0K4M=)x{vUhTZ6TB0mIF+`aY2^u|l6%gmUjZ~YJ;{C1Zze|StUcFmX_8Rmv`=}tNE8jS56
zBXgNNP^VOZ+a4*iAH+4b^)u_ZX<(uGjF1Za{0sa)0~BE7n+Ej<5Kzb8M)H3LC@D8#
zR|6wkM>8Aif5MYjY^QWTJ!(+QIhCbt_SLk7uPal<`L2TgrUVme$>2g1{Ze{GtefswAz?)>97K8~F)x+V&6@aK0<
z52E*ecM-c#0&jmNcxtZPLkU;m1bK6?L=A>VCt$W1Hn3r?|L;N)7rKWV14mr&g`$XB
z!i!Ee{UE!Dx1UCKRxV4|Et9fTyKmY&^#uOUvl_WNS=Ih`M#n(@TiBP@voccFvve|&
z)ie7S><7i`(Dm!04&}IPu9Y$d>jh7OG35!h5L%P8s{RqcRy+pW0
zMjdU>VKG^;v$t6){n#F8)*Cv!w;d+Q9<3wrQ#Ni(cLg4wG4uA71$bNK&)4`BteJH-
zrPnAVz%FfRtZtMt@CL*>Nq<#v+2;~~TtQ{}L7jjrnu6EOV2*uX4$?EF@8>y~X#Ajj
zfMR^ml0SeFmQ$Y@vCz!}Srv2VB$*yDF{jgwk=Kn~90dVGrqK^4BBt(Rwm$&VB?De4
zm0vgmmR)xPmj
zz)W|^qzBjx%kO(Fyr>2lCNoZP5-r^lR9FtEC#Dz5{Acs)>QLQPKmY-WBK@D{|M&EQ
zprx6SwWElojlQ1czq~$`b01tKEN`;a$q8D8c+2>u#3sx6->j=zL11xu~Y3^$Sv$-0!s}!=)XNe_PqrAS73IR
z>Z(KLU_{)@dBSWf-}w7u1l^EgZO7eilIydV?|A6{b?>P3Jz2s5nF+UEV0?(h+6p&<
z3}58o1pANV>bJp>Z26)4{xcuR{yCwydHy-jlYA%<&1fCOLoP;|;dwA7gU82v_b^!9
zi8HAZCKCeu)9hx$sf&{wBL0c?hhUo=R_aXUcaXL7=|<<7!{9RJ#SL2>$|H}_oXK({
zJmk3)DbCb1O!*q8X2TRk5k;hbS{syYBO5MH)OjycncV$wQIHoj*Or))uL?{an2^s@
zWR9sFs>pM#W*Y1}vDP!|8QrfFjk#7S+FdGOu@N!jt=%iWXZ-R53{Jb^c6YzJY9Cb1
zOMDJaQUl?J!>nilmO5?0lH=4`a-d374|z4M_P;W~F<4<^NEWay2~Sl<47+w1#BG
z0zNB_$K*CS3pEVOb)bAZiB`{UnXpQJy8xuFxFG7(B$}-#!=CsOW+S5cWyW1)hTe&!
zly#A>;9IoI9F&Z(M0o1tBrO)ihZF0`3>_leFnuqjHYSRGUgp-F(Xe$(Fu@U&&_Wmk
z!{n{PZ@`ku6KOsw;TRbyu_!7lkXBX4mlzo+pH*_qVkJVBY5B$5Ot7{MgOu6jcTNEe
zd@BYQ<+VB;q0XCEYXVp`E_MWS2Lf%C1Rte4B@||1EW1hCoRP{~vX*JqPV+QQFc`RY
zF0{g?c_|~ecepU{oDf3W@*tLzU!;*}&|>!Pk@s?xqJY_U`oSLI(7OAol^*m{#)d<3
zws-2nc~+?QLD0Gf6)L(GPDZ-Co_S~LHTo`-4lDLtUOEG=}%X0TJrfF7pjEE5^qg(X_{>Ep69_f%B
zRzIym6V#M1&(O1qj)k(Rgl7S*n#X?9mB-3Wp{{#HGDW_jTi!Fw_iSM^fu=Qi?J?;F
zR5Jb-JdBH=R}EliQtF=mn@FHPAmwEys6wU;*qwqwjN#6-jN
zbp%>?9G4N(Snj%{;B=C?wRS7*b0;lCd8ka1Fry#iB{MAa}m)%
zL=7A?JpM`)RN@ipm(@!Oi=rY}G=IP`QR5Q^8T2bgH_>NAh#nx#wj&fm=xuAGBY@GF
zgL`ItBYtv)j(^b>AZ<`1adO&a-w(w=2?|Te9p+Big5tJ3;;M!e-3lJIYR9I8)^U?y`WV1^|?@7a>rbn(@U0VSIU-*wgZ}NYqNHO
zERGf^vqw=a-qdnBjd%9#n}2XtrF%CzGx+mcXxw#J3nB
zWDHzNfcgJUl4vYkOkwW;eZsB{cjg0;5I
zU!Ng_HGpVso))(O$_k+=haDbq9Xi6xCS{zmM&>L0&C6K%7IVZNQ=rS3uI`C;)i7Qc
z|96(>9|ac*eK-#xf1T&-zm4+0IMM%(_d+%<)|NJUhJt#Qmil@I7XQS2u1A|?UT|=5
zL2zkjaA#+5cmQ~E-ogPR0Nfd_+Vq!Cg*OB=#fO23U*?ob^9SGyX|hbwK`vp#la1GX3kllK(%3qu^+7q-XWd
z!2~I2$)Ly~^0>5LCb!K&qYls&EXkwmvAh%vh2)WuMtPAFGH`EN+t}HylCIPIx&8vl
z`2gwK34qew3*hS^FyeMG6P3iCBy%{P%1ZlNm+-WFO~Chq+h5~1zRNFNJ-G<+AJ4Ll
zw%xwe=IF`P3pCU)hIx8K^y_O0A#;z!%{-Fu!D7F{k~VxObv^pomG$Oab4vVtS5QZI
z?gjbWXz6tb2pT(RbghMWNM$WwbKQA1uFG5{oI%u!)Z=~ySYf@t@iL~5YUHezSCVfz
zb@DSu@*F-L{ycqzxQaL-hb3BVuNaL?av|4UWOKouJS_6fjRqS_8Dw6ki{WvKeUTHr
z_S{BL9RB{J=gt`CxNQb$*iH03k=Q|zqf>$uICPoOe>%4YC$XrBkR~D$c|z{pP9sD*i{(4
zOkS)jFRg%{W*wYswC1}SLEkk2R9d9BV&63#9q)6`A>nXq|-I_E%x&4a9%;mrYXI=R5x{wuQew
zGtqyu;Qqmpidh@m{3`@iJeOZrM*NDVtD_czgeKWV-qTc%YzZZ?nnxCZEGYLTQOkUdd8u=g9~ase+yE+N~m<=g4zPNPq8{erSVvXaFq};`m?f)hE3I=
zMVmV9=oQz&12%24NeT)uW~Ot3&7(QdrELz
zOgkltx8nkY?3MX`%-i4-7v>Ok`s_bqGG0Ly7#uv@PB0jH5qU&@=s2NS~pW%
z;2lsbkeI=|#CEB@fe`q0Yt%oW4c@a*?aCy*e9c$#C>D1`cYBG=dB))FHjzBZ;+ge$(XWyMBYFG{n);-Y+H00Q$YkV5Hgw-rcmFFbpI%$ebA!zxa6xfX8Z;0KdPDcJ?+;8!F{2DZuOkUQ&R>#^vs>qks#1#>utCvugNue6
zC~w)%z;6^ziNgW3%Uz}2e3d7o2v~Q`eHq%&TNrJm5CsPf1*mOUH}t3r+t=hgj-9en
z4Zk*iAmo4jbhK#*S5$}^7Qgx;V>cSv9NdA~9zpf_eNN1K2yai$CED*C%fB>4Civ-t
zJz$=?;X9t|v55mkr!T5J3D@+k+Xt`3Cj3jrHw};6z&MJ1?ktt~TK3VGgwRjm60Jfx
zn^3NNBGxlZaqA
z8UhVuP@Zt%Padl|D=De^8ZnqJY6Rh%9fZGiLG`l%u1IRmN0(C>&%tiru3jLr!_iUH
z%J=lOMg46-QZO2@YPpIeSgHZN4~E}iy(dUhSrBrunusN=?os=+N*Q%@n9!F$kyR3E
ze=XoW3%pS@7Ebrms`z>P_@s{tBBHzlUgqJS30`Fz@_t}(RFWf?VcoH#3zak%Vz+ry
z{~E)%@*NiQL2Sn(MOjVUuZ^VaMxDaESWooAGR@yZxH=7$X$8SCg5XevKZW8{#JMv)(e@zT{RNv=rrm!RV0Zt;0mGOkSn3760&r)G>06cue
z=f7}{QVWu>dw+{rf6xE{k^a9;^iLcuREKiaSWMy-Ij<)grX!NpzrZ8~)u(dKWbX~6
zZm6T-61N-`twTYQS8K|#BCRtd;UM|#*Dy2J+2E*WmOI0$WokjrP9Y|!vNksdmU_x2
z!L^COX_e+xL{s?Pc`fGdY$(e0%FDC)o$YYV^L!yQrQqZJL5*Z}be!o~7y*A%j_Tdm
z=N-g_b|v4UvFqE%1N}_dp|SfX;`v4!gWfp=EjMZcWijz#QnCV
zSNg3xC6Ht}d^ifaTiMb(p^vTo1)Y}`zZxZGnd?=VzqK-ayT=AKe?9Ai4C4|F=J_n7
zLrrq~?I&%}Hci*Hu`|RR&R*N}3rookPbbz!~>u&0L1?hXr7dA8apb8_-o5o
zw=3A}GjC$kuj@Cpt})+;qnpu_t_lzaq|jbGPwWatYfDJyXJROLHT=&)2(Soy>!Ib*HvyhL
z!LP61dE4DO73dL)WJ>V?AYWHkp|yF^(oP}opS`kfVSmC{n(1j0U|U3(F=@pabclPe
z=CF&@#lk_``jC)1LHt4qEG4tM1V@QSn;aRLX3=R5NtII81dg%0JO=&_+HxNiCh!eR9m}~3GPDmJMK;8}R
z6*U%uN#KQmd3ryM;)jLqh@Y|RTEe@i$nEQ;eVAuzm1aB)+QB5e>~xU&JjOWy+s&Ma
zVLf0dezNR{0);MUc8JnPwEk1QrW*q|uyC*MN0m|VBQ;it7HxgGhy?_ZXSxHDXq6Lo35sbn9Ym=X5Q|#rKw3HE(?QRl^
zI-&Z=(M-57%xIrv7Zrz=s1Z|WVA0f(xb*di1TUr)HcjT%5d%jC=d&X#!S7*XyexrD
zCuxFg(E^qWgJt_x*s}_QIo(D`+T#Le#o~5g5fK(Q&+^a;u7
z-wT<^nQODH#ji>TqTC@<`JnT}oJt(Y@{FEDUR4!k3+>%o;r
zj)wBq8j>aY-0Y@r71fz!R_s^L?}T&bOFe%$U3I`$qigfX=pENq=>Ji@BNp{PmgUUl
zm&$A~WX_tjn7ugBgPWsaQ%s+QwtCxu$9i##lpCBP?7JA96*vn;pTCQs?#AX$C|a&5
zb7W$!eC(uEq3UDS}6B%dBmAp1Dt+A0ga=?A`vHda7Ct3PZRTvE}$GksIkCCtvThm9e3`o-~Bf
zCZV0cQ15V$qL^d*avIgawdb_rAqUe=waue%)f#(bU{7}`cA3W}yVeg$c{v4p
zV`Jly>6f(fF*-%g^W2!s`Ew1~>5V)av`qe&8Wb*o^bX|UzX?d*|SnmF#!}%)5#y8|3&3k&J@WH{xC(UPjZ^pZSG<~lYT0c7}
zbAy5S{kfUK@fu54;)Oott8jI8?tn?uIu0^_xTV;8adP+>f9ULm@Aw*RH80Nv9LC!`I
zflty6*v8$eW^3-=#Md(p>7I7}=2;?v9lLgVyj(WK`RFv`KEC8k3Tx9
zo#pXJO)<$SyovIWcH~g-L6#(4ab5cYfB7kpc|yL_Ko$EHOR|Gxvh14eSV*x$WU}o7
z-$X(Y{OFnri~%NK+CBHPq2I;v)3NAd`>}1=*9=6!w!8eJdn?cetZOoG8|VXo(uMaT
zMfPF5)0}#v;kRwvX9M9K0@aQ35)Jn3mIBp{^CFGnjd0^3_2SiY&9>X_d(FD*;d{-p
zivZ*^6L<~MwH?R@`r!-32l=6g@&$P#BJ~1#Gkmg7`T?~glU@`1Oo;M@dQ*(CGo5-v
zebY}yec)mEV!}p25yFy}KqUZ>pNk}M&
zAb7EPr9H`Ru?CN8hB?n`C*3dV@rNshInL#bd6eq$mn%$0D~5SA;+=_Udha_?1zRoz
zLp9-;a05$2cE9p%U+r4lpsTWi4Gedu4si}oj(3oe^IZn5_W;)ck^+*Uv
z8M#N{V$)M+kE~5-RTDmsaPu?EGJ8GP>9R%F@zUrmkYR{Wr
zb}!0qm&$KR+?tWzG*%>llaE{yh|1#anQj3o{IcS0eZ%5yu||eZ{JlL=evA|wP~nfK
zSAW{7>M2$c^NxOP6D|*eSLyk>7qhzonK`iRLkC3-i=2G4>?BOT=v~}O0Z|@8+WNvT
z-ZkB$ZdrT3pUDd#3)331jfb@A&gs~D_L@%d%G2UnEZSG9yCrS++Uh1-7ep00yQ#$0
zCUAfu+O0CK>)a+Z`0FeeIR&GuMoc#bdgajj3M$;an)o5E66|S{KlR5Y=v&<=_ym7^
z1hU=;%_n1GzkR}SznEI?=wdCr;WR$LjlZ)R29o9$=w`a-eMBWXet%Qs%S3*`u-5v1
zb?Aj*w|x8b2VJa4C7?SbTGqj`z7o9Y^pkb&Ao1V)sowGkr$v{3Ag@d~Ya^i@_Kc^^
zLd$<_?l*U~2oZ$9n^GUPvWEn#dR|<$z-yf1Fb{Vje~#Y=rGZcm=Au_Ck91;}>3FaV
z`=&ML7+#C6YwXom-Y2ztsYT2y7`kjgo#yLF`x2$>6pf<(TIg-?qiG1be4uoePc0|!
zvkrG)iK-Jz~Tf8!wAH%o#H_HJzc(@fO+Ov_U
zNldybHSd&BUh0-B0v9lm42N3Pk%h;TcDP}xm
zb!OmZPu3Tg@>IEdnf#KOOYVZ>r2^gN6iIRObQN9j>*Zaq0w+M7>FAxO-T~L?=k5w7
z+O9;`e0`VQI)tIy6m;H_g1#}a)<`G
zyFM(Tidhw2?p7KX2VsZRt5gmsi`8v<EJC(rF55!3Wi2Zg|81tYh%DP%oETSM%TA565W?#Ff(h%+@Avk+4&datIjg0;(OH$ZPPIizJ~c4fAVy07F2DE
zlg8m{k>e~=Rvm-)gIxt+gDvkupUJD>X(?)yxj!TeClylqw}e(%yP5jcJZA**Xd*w^
zimfbem_oi&cPKruKzJ!PfGhD1C+nZx4k$g6bW$pA>y`be!P=faG5v4g(D
zS|}Sf<>QkxZ*!h8Zz&$(fNM}NCYTMur`9_EV^_&}b`+rsYMu0=HA{ZJxx$|q#i7Jw
z5Tmgu6=0Xq=0@DnysK8I?N=-zwbv?y
z*E?Ssy{A?gz1ym|cvB%a4DrsbRb0~E4F>gVhEarvaM5F^Yt#60hAOd)_jjdJllpt5
z^Omo8
zJDyL>R{!*j2!nU%ca>t1^`FVYJ?3Eyi7Zl6g6e&VKTJ_odlGIuQzP_@!{#N2ysOMK;J-rpEGMSk*BE@%Qkf$A~^E1V)ZH>EhF)ee@?
z`gl#rze+*6kh?OMT0L!JtxcougGtR2P#E$!4z3oSUqFI2$4+9%9bcu
z&(-zT+eANYv*<*#qg$)~3|ZL~2cWUc)p{Vqm~({RX*Ch)f=~t9<%E7y|dZ;KDiF(HmiG}%ZQ{L^*o3n|2^3k
z#2RgfNq8UK9n|=|FiA&n+1Gy|Ns*?sXw?5^8vn5;gZh6WN&n`xoeUg>j0|l4*RBl3
zZ3P@9)GurAi(o_v2^`ACnLkNnaIyYYWuU#m{zXG`3~3XNuD8bZV$JoNlNZ)yHy3=n
z<#b(VFzn9Y?-x2V-GI+4GF_-NakAFqjf88@W6$HQ&F-(SeaIfhY!W-DaZY7N&v+r!
zai|TYr)>3bs122;c@m-*>M*55#|?3PxSVrUnLS`uN6*}SKi?)}4&@qJ#K|LU;999>
zBWOuQnqkikk6GrzyUwY7{Zi$`~}EFpEO4VaDTtK{U@lE?y@&XB)Oxv63_k72qPoa%s}=O0ru2fw+)Tx`O@~U$L#Y)r
z>O8bGe0@ti6=Qy6%rADPG<-vGJ+I)Jgh*!#5jcRzYd_XFyqWkEZZUD(CobvYh<^@mOHG+e@{t!#
z`5S%ZSO>v7#JKzM`cQIVZw^b>1aj-_TTA(pqMgP$boOmvRp-TS34}bw0s)par}tlU
zB$0lk6{Ma9J78YU0du2t3NfDoj>`%FG859wi<88YF8+O!>Jfatp~rKg1C)DkGdGfO
zGgKIND9mmV`?&)vgUcd354=PAWP_I#SPVmj;{4U}){=t8ep)hTh;Sa4?2Plt-M{3M
zEJ+D-!8JG^irC$+w`N)|_eC!hG0vUvgtsH4!@fE8%i=aO-XXjeSL_V+K`4(*4ooUf
z4Bm_woWYuh^)G>H2OC0^Dr*Ngf=EH22bnzWlFN5gl!RW7Nn_QHrq$=@rc
z-E4a}hI2@vRpQFlVunU?hebU2qF?VjDF7ngNBaLA5G*6_qI3PknG8N{LH=(_`u}0m
zD4RODnL7O!0O+e^D~}Z1yVPw?>
z!qySv#_$w|57CP04$;-mDa>EP%&SKl^1r6;A{a(hpp89j
zNP@pX7mlEBD+xo(U#SfLfSyidzk-@K+=WsmpBo%K@xU4L+JjZ2a6_<0QvOg6H!Lb0
zakKP*y|
zk&@}FgN4sF^ag{Koq|^k&pK;WAn5&3-2~44_ar$`R+k_iBMIbXP%xkncFStWI
zXHCMqriVzUL7cU;8*hmJecASER*1cQLZmvM#|!KK<7iQKv3L4}ME`^PO|I(jKM7$X
zu4ZQc0mh{$%h}KUPkfY%ot=@!5+0yMQY^HaoYq&biW(_|5H<3BMn)drJloFkd_)gg
zFbYu#3LVZ5LJ)zaoksX)B3deV)${gnrCrd^?*(NWf&q@>qS^@Nv8mkh&)GKQgAHH9
z^|D0vjx;qHXsSOU-(l5EL#mG%BP!69CQ^(~%^W~5s!?GK+wQk|;f7Czq(+4cALb-K
zwCn1}0yx1Jh$&M#p@57BdeFN1X*SNMPvB&=BvJ1aa_6qa8YjAu=9mUeX?2nlz6k%`
zw=^Tr^=-n^YBH5@p%l_U2Ds?bSnrMojrHkFwTuBJSRwtS6F?l
zqp`P9aU5IaMFe5Vw3O%F<8`~8;QB_huDFhojxpS1ZmKiaa*Ot^<>ViqPZ;=eY%Gnc
zDUzNkA1P;e2|bxF_c*JRolagSt3zT~>Y0&F>M$oBGAi9u+9`_v=qAk)sATJ;sRu^7
zAeQAeDgh&=~LH@cr5zGyBa+|Tu1$F^7F&$xClG+;ud(UCu_o(Y@4r~|?g@^_&`7yY0
z;|RW}0~Qsc{(VQ0i16D8w2v5hBq#XzWJrln54L#t#6c>l^JTQu8?MnDg57H$X$1N0
zNF~tLq11QUZRO%#%R~1~|5+!e1ikIT1D3(VIZ?KRc36*!nIHQs3_Ww9Q+1vtF&-U!
zQvgr1QR8O5!;wN+qJx_>x_HlSLlgs@_1^9Nf`jWv2l}SEkk9hc(0Yn1EpqCu}Y8PyT+X!GRnZ@(#7ARXVrBdg$ap-iXp{04oW6s(d
zGtcu5k8V$Pncwp&k93MDqUlO!*5gMEaZA9srJ9H(R>F-6S8-3>x7VmPKV>bBUwW?h
z>`e!VyOI~|t)^smtb0vO3+%F7Y9`2)RW((_Q$0>4_Rq4d$()jwCgt>J-qw5~$
z$v3U4)T221KWaOytUPUt_d7)j{R~Yv9%FbKDp>V&;}vCYS6PbPMwpDkum{d0mlhZ2
z+jd3VWGPHrS3|imQ%Kj+J@>FvYN;>PRrNX{2(0KTv61*2P0SkP(iOVM1)4gnJbjcr
zDTXpVEjUYlrc{OFRpL#W2L5W4PI>0OR=sy#m*}Oqe!k&WO>w=~XmX2*Eo{nbHUlfw
zdRyF8cwQIZr?4+*+@HG1T~TE<2-uJMlw@@L`q*=fJ(XflW6F!cdB${HQ(3&j4<5v9
zrQJv4sg9DVOl7Qv3-M?U{wZp_qXN*BJ-F7)y4#kNDawh9>k_nE?eNi;>5r)V
zHu3f|q8T#Q68zr2B1Q2I562}q3bFUgsw29TY`n7K5Q@-mtbhMPNB2Nefr@AtkamRJ
zH($tK0D+&HN2#|aa?dpKxNzV)N~6(sUnWaWGo57_&7
zE_1v4rwN`dzCHzSM)q4e-|E?o#AnG8=UIBuOvgVW
zVwl=cWaei&Xl0KZwKmFk!c#;o`;)}O??t0kMqy@i=mM`OYP83TYDjt?Lt-!aq5h>e
zdVg2f#BVZ7O<>kmaPjxYi0{kw=Hfd1bqbmFw#GEZCEN@@beKEigdf+A&L|$#rfCU9
z<=NmZP!mU=T|n>rfah-={}Atqo~41^VF!Sa%9_vpaEJp+GY&sZqC>a|ofHuH)MHWPJqO<6ryDaKXHXERDlgY2nQ
zX~acm7A9LoTUq~y5`#`Whi=bCP3#gwZAIz|rLM$ywWN_@hfmiRB%1e|(HOFY>l9}#
zo-E6zYYO)JYpkbjNdoq()n1wn!crc+t!ain=AG7yF8LZ-{T;$~wKPnbZD8hPLRfVp
zkEve=?FI7me7o*g{(M!Jo9BIpQ@44z*k($Pa(KrBO{Ni7x0$Ic;-IDelE5ym#A}W7
zhGsK{{!sa*=o;czsioe#uzA`_ZNfFRsrsF^dYa|a8))%u5WwdZX#bZ?|BB~Y8tQEd<
zz_u#8nG%#(HO0~SgBL9r+731atCbs%^V8qI#Ey1igx}8SQU}gX$5ZJ;87C^UIr9YL
zn#P@g2eaGN&zypLzmFmB{F$27xL
zcsrcGKX9_URDhyRKrUvX)#4gMv@)yI*i`M5w9}Kll<5Lrf$wP66*%*4kvYyutS!J~
z3Pa2A$;z9W43VS-rC3FU4A5!LF^(aA3F1isbGGDB_zBdrc$(iQK<~nBYru2rP4Y9t
zb^xz2gs^UJi`kU$&`+phDGbco#V6Zx-Nvlnt1fNDue{X%!Zzt!i!f*0$T`uCna)%?
z>44Dv$WtYG8=7DD7w?EavM;A$)t$+}g050MSzUGNQcJJhz|#jlE#$;+l_Y-B&@0+4
z{DkmXH0=jB)**H2nvYx>=T#GjJ<{#v6HjI>>MgR1X`20hrcD?3M9WnP^VV2PsOOK`
zKi~)EtzPZEj+B;_*B9okQTLS&{t5S6{<=IVogC(^XqsDJAOAFb56Lw5*^&X)7A_o$
zak|Rn+CMEm>-8_jS1>m%NM4qz_X%h_ILb4Rzd
z%|g_^yYIf}hjFZi;k;50xw0$af4B_ocEkH#nFY~HO5vRcjQGdmcfKt4*|^>Vz16Rg
zlO4RpYwSpuvVEGEKZXu{4gIom6BxW%C*-e*`#W-TQRcW^Y6vpT`(CNKXeOp_a{CDm
zA(G#Jl3*PkJ$dfjr!o_7cZY#t-nG;8_fz{`SwCXS*B<+%)AV=L)7zlK4?HMl@~p)@
zO;v@}UB}m4^(J4r)G`-mO%309yRigY3hzRVz75bM@?P0$qmW0%=DqPtyZM6S&5|u%>42zU2O->XDarFnyXYNDdu{)
zjvAF6MKwu%yv};6a)bsGYU(jcPDPvM3X!+fZ1qI$XH0*&pB<7af0&)FK<+Ff{G
zt$KP?d)3{Zgwk7)aSHRMyVW=0ys>gOAeF76*R5cSSmmBMTKJ_}%Zf3X
zr(PmlLgl;Sdc7W(@li?)og$g5>>@!>RY-Asw9ta=yK+jDPpC4
z;bsqpQ9xlUkAnV>73KUmPbu~hA*dwOg=gvYe?%W6xXn?_^qgWU6+DH-*;cK0up>VD
zk}{@RdvR>lMCXpLm}{PNA=T@bU)QRNuy35ENL^(rX|RctZuLa9>q(H63YD
ztZbSbrcj1=&b4T=z9}S*ZoI>`7=47)a4}7A#cys^c5*s
zSIkhyVjT2TCN*Yg1$HIyg>r_jd!TKv(>#2gyc(!I@#s0TBKYRt+-jO|3GTVq!SdAC
z;&W{kTszqgzfBSUzZJxs>+zT*2#_iyGkk`;_WL7=8uX_U=AacZlLWHONa@~OH2`B%
z!BvGY9C~zn?9t#zEG05cLE|go0N6*+@@D2zB2glBJN
zw?dhdrM$iyPNMOX>*gY}Bhd!4>nGL7M{L2-*XAxB|}yg*h>8`kts}Y$|$|F&h;W-4EZs
z{}A@l?8i~7!Z0}pb{9gr@O#-5u(;3x$0_eRp)>!&^Is~^xljU?+{c8+bjx$4zq
z7Vzq%bgL1Ws$kPmMgVXG1i
zS^Wp^3dx~5G?G#n8p~oll(7NG)SKZp`|Kw$Zy!V7*z}WR-`*W$J=RNSho57?4C#BNfL3v+Vc+M4D()<>9kVM
z3Vk8z`toW>KM1RjX;?S2FG#}O@-9e16OU|k_O&t;hr0`h`+au*NhWE}+90kp&~|Wn
zH?kgO4k?I7$Hv)FC?s(93&EetN(qLLh_9l}Qb!P)1WJ8bC2@cE5ci(?xEfQMX$%RT
z`8UelhOga+uiYd|W!n%M)VO;T_FDOcx?)*O|?O*ZFKEFEYDz=BdIX<8=+GU>QyVx8T2sC~J!Ik?qQ;
z7gBElo`YGEWL&vJPWlo*qI#vcI(kTAGlc!ITPMEQnDaWqR-^xKr+?XrxPL~Yi%0&uhqWg1DAneGd
zpojcXvFe<~mKsGu-KcxJ+fUb*t$eEe&wsiTUt%+T?dH$
zs8oA-H&NrQ%vQ_HebaARee};=5HRU{54`u(w9Q*5mAT6komhpv
z)K`jQIAoU?o;7g5M+#eoy;I<_2`K@UrZvm`S{GiJ;9
z2h+C6f-Q>g>k^8EoGpr{dFc+O;T|AeO2QZ-MMve`>xc^o7amnxN
zj;>9hMQdalxcsm7wZ4{%)zpooloLFNnzR;#qKEiu_I1%4>i@1|l1U>HA5)>>j&s8g
z-(^`nlSadfo)r)qQsGL_9SH2mX+U^X3KvO1;vLd!h@CV!7AG_!m({$f;~EF>O##df+Ndr#_^2R)Ql=_@nypqCQUVqY?I0H!CFxH~7jkB1$CI
zn$`FqUG3G#VcbomEvdRtA;U-(z-IJiv|LP6QSzIA(63cTBzvsvEMTlScN`fa`go*-
z=`5%qOJnN(>k`jNS;WCtR5*g~kz`1iFoN{aw6fO-%ILu+ytsC9Vd_cw8Rpz8$n#Xh
zVQkje2iA>tLvJQFd8CYPMv2JtOS*wwr+Q954x((3RgO)Sqn%a9Ms1z4&Kq!s#g5#I
z{CH3P8c}UIUKGA>my{W;(9nz%P?b`QPce>9$pK5xXI&v4Zm?*RM@%@8v$}%grm3y+
zgzZ$Jk*9Eibl9R)pfTGWuVzjv)Z!)FXX;>i^11${iWkD?+$ySPSzYAkv(jw9%e(R5
z0#8k-{-y>2>#nt8K;>Li?JDJ4xzohP#PEO5d;@n{1vXpBOC=!`Xr`ZH&e-C=5QOP?_AIU9{SG<$;Z7v|Zv-6@j4P_L4cY3pWgWV6^jC@6Y
zwvE~>w^wges#QLJIFUbtn*kncj}Xu3E8a1@5$3an=+6s=>U^(O0BNpTi`ArAIgSz$+>}u-cqd_?ZNcfU{c+^ahD|jQtb{Y)GI=-2>d&M-8|WA8qq=bDeiJG
z?yI{mM|ZXQ)yp%~`%k7l`McIv?i>B@AF+D*D_&t(v&I>P=9U}xHVpcgA^e&7_e*
zN0v-y;N?f$RqgG2$mdrKUqR?vrk*qFPN={YsH}Mee%0w=Al5E`DB4-0>Tx#wyL*sc
zh%>KPZs3tk))s;IueuE7vgQv&;VUmujJCY2Sb@4MDwHiCWX`dIY{HnD}T#
zcNz~J6e9J)gUgvC*sH(re0HLKbT{rn7h>%aonMX|VS)EHS!W1u-1CG&pY{n4nEM}r
zuiAOUg&U>M)Nen0W8R5<$ju~+C5%PZ78H*
zz*vC`r)!ZQX$sKV675`)7WzH8hTt_W0^B}=Ed|(fWXs4AuI^X1DBE3%ELHyY27m7K
zgz+RiJ)2ve#4#V4?3(uH*X&(N-~qQQc+HwvW=C)pRG64RXInvSO}D=n}K>YuTa?Sg*z;m4OQZC8gjQ4$H&
zlBGyfJi9%^bqZVFHE#B2f~ndLCtn@;w=%)P{Ku28;{0pbt>13;#}@@fU1(;_ar-+O
zHg^{&Ud4+#u(^JEGC3r)jU%rnu3l_5ksOFm{FM4>T%P=t0GaZOn&+oz%+w}|8z<~+
z=1*6PJ;Sb)uYY7=IpKIebhkPI&h~U<4jiJpHhPHRtQjlK6+tOBx6e
zZI_h4Z4EOx7j?+1I6W6dD?fgao|9}ImIV4`4wq^kUZU~L(dnzp)27QKox1yT0=SD%
z6iK(dPImYZ!OopnvO7^^+|zHrLbi6ExUp}-A-rISbu2@Grto{_ROT5-y+)vN_k{=s
zhDO1qM5pG~MBMy_UOe?iS^)cAWQo+DQNQe1t4oI(DxK4l?3DM$KpgwVNZkIA_sK3^
zAmqXQ7AQ`%_+#eF^{s_H!sSzHuB_>3t8b$
zEqL}!F4u=30mHb?F%=0s*Oqm^TjN!Hgbf|1g2>;TGOB9}#h)=%3TsOjo>g7)-?gCC<$g94u7Ok8<0)f8!JO52GRzLY|W1lyCvi+F0sxAX8?RI(Z!=LPY
zv9~HO53@%uh2Ou=P~8h&`Ca)C@#%|fE%odnU-=;NZHc}c?+Xt4kWcvL7~Q478JzI-
z%9vh(BLS0#7=Tv^2+d2npFm@Gm^H`DtB)0Q0es3?+69XdMremmWkhmZXjEnf@RJL(kp=i}m
zs2z~lu!^6zsjqox%!#!9l$uFEAYwK64Z6v}M?N#kDf
zo)y^ZKkG!Aa=^xNF5VNIxV^@IpwV+sIs7ube&69&bEt@rhkh>c
z??u$dz4`P?j;#c=K}|lGD6WA8YYE+PoHT8*mw>3kifhLC$D{Hny^&PvXSB;bbG~QV
zRl$BZfNzREM#Xbye8(LI?c1h01eiD$ByRzL%W4WJP-GCLzT8DE&W6j{J7$A83Wu1A
zhser>_~eXlzasU3DFSZkAdZ$?e!U}SSNO}AKD(>HNSdbSgI21b;dn*5A1vO3gG()?%KjLX5)~sXmc#UVwSKjACZg&A&BW0%T7H6R6?tJmdE*s
zl8T#N#iLTo-&&%I&3T5v72vwiGO3W@K}6^k38}mfOgq37&_IBk0TE%Axbdna8PZga
z)li_Xf@i^xcBo>785b$sP_FQ3;$zT?MSP!Kd#~94s-3<6`g3WxkegfOe6cS=f|PBc
zde|{ty>%N2av)^L1o3|V${m%-_+pXfu){Zlre)#^EJ$ho49l=K?O7NTO6pi+;iXda
zkzxFo$@^skrI&Kph8BeaA5v(wL3H^X&F+^x>#W7sx0oTL9Fb`S&RGmh{@@Ziyy87e
zfm3V{tJb+|`U%dB}x`AEFU`e*1PcVs<=#>sYscSI~Zr
zA?wNzAPR4edMypeAN%73#~6#yo?a4Am*HoYC0`heXi??J5&PpkoRU-!2K+;49AwwU
z5>6ZAq-8RY|3}6mR8g)n7G`Ecng-*{X)l~X>IkUYA?>HW5L+xdPD*24_7+@31}rp7f{
zDVTSi(@i|0AH|e-=|hABQE*xI!t&IEr}R4e*%`?u|8@+@{2}Y)o6R%7tW@4|>p)$<
zzKg|Sz~E|a=(Gz;;R3t$$$cdaQmU5&Bu?NRkfp_~;K}ZU*5&{_L5L|hEQmADwcU2-Qix`g=U{ncpApb(llIMpe`cUnDs-X)S(^ABw
z3U+ze=%m^z$xr0!8*K-7KF3g%4_MiyMqnmsFA`j0`oS;}<#`d8v%`1xHb~T;Ap!n#
zEg~zs0b`H(oPVK_^r$X|eEE2A?tPy$#NnLl6&CCoiB|yBZ6lo9Mt>^-=RH(Xyq5}{
z(!ma8cA@B-66r(d$=2(_8!@)?!^^<8SZ|9mN2XY|i&FTW7RwJ4B88&MvQF=z5W
zVQLMsYW9pg9n{{R0#Jiq$!<9Dy+1DsJBRk}vaZQHZTMiwz_6Xx9iqhe#B=6DRCo4!
zByYnWxn1l6W*bi-3^QfdfS5zSINWImsy*%tvyOqznAFzzYwQc_*OYkicaMFz;NLj@
zN1!2mzD>k1@PrONb)qu@RemY12HV
z{24*zC`Mv=!4jloski*Df+~&$Q0$lxj0JUP9+C|-J4#aEVG1D$}J81V}vfWlV5
zj=2j`!AFL2rU+bYJ^&XTfr|AFwS?`1A~zE3TeV$X{Uz6UvZ9HRSvTmXxhIOXtJYH(6z!`c`>QvEN~}P=h?GhqV%efj!i$?E|p~Y#Qm2O
zC@qouD7#|sW5{@cz-PE)L-E|aQb5WBT!e~ue(g+Vz&(_Bx5PX2b83P99A}hW-wOYB
zZla`v$f#^_0B*j^A2L@~%bE%aLi3
zE+m(4s|+md3jC`z5^J{#&9JW6h3B<153Ku3Wd7{OauzM4|D;>eH!LexqAytD^9jua
zy?Q1J;U;~&aKN1-f{@QyE4e5EM|9g@%4ec4@u)qwWLK})H~OR>>}6SJ`Xb&`FJVvW
zeif*)%@!^RM0aB%E}5k%!WK$U$PQt?)ksfTxK}PBN;zv0$(0z8Y!1ekE(T5Bs55Hv
z=(*r|Z>F8XUSSD`gkqJZxdWm99CN(C0!IX0Rk6LClnc=N}Lx!?3L>yL7yO&O6s()U|q%V(nfLW4*>!^gkM1uciLsrdfe-}1`xs&>t_q00`;nlqx<6xuKWjba6
z-$H4qJd%&~6z0lO4v6qHm^YR5gRK5I<0)_C@Umtxde(oLJkCKGVH+ydnkIobp*YBX
z=DMyUJML=RIFKA?0d^sSKRjXm7bV8YNK29H*8#?!Re#JE=vb*TyMF#EGFsFP9blt}^X8mr
zBk-Z+RyXQGXt}HZ?6GW@Q;1q{(Ekt{q<1X5ufM;9$v<*Q#}ofp@nBcC6$%Vu91OI?
z>}eEFwr0$?Gh;u?m1idQ*txS60jC-7$ra`5jBk4$rYhZ<%SLZR^RRe*v?DB@mD7RA
znGBWr@~HQak;qVBqHsd;iQJhpHN)Ej>Lw{M7eOmb;C5omVZ9@!a>BJ^LTCDZ+mXXV
z2ZBib6SnobrQ9^w9OKOBKGL4#1-m)_uxGj4Zcpe&1rz3>X1d=N;#|_iJeps<(LHrX
zTm(SsB`rSlNdMt>SVjq1d1U$LfnJ}Vt-(s_vvC1P8EUy^N9QyU}cY}
z0`nW2e29LK4*dK0iFN*ZYB=??Z*4`4V&z0IJTj+XF-Q#+&-?&XzF5z;z!O)Z4Q898&12o)8)5oVE#7``
zcy#A{i})N0W+&*khsfIkMgNw_)qs6lV?D9141e8Evpv&5(H?fpNSQuSgES}24fesF
z;TzxYQVWQ#Vn!8y*|8ABJJ?h3M_82?d!ZSTmwcC2emt8H`wAE}uO
zERF5oR@-!;fn^f)5xrs;QaFQ-CbvD|o;Tr%+=Gugw_7p5{3C)Pt>h3cW>7-h8{w0v
zI}hCje(N5*)%QZK1^U_}{Q#R11x})~-m_`YaOjdgNtw#kX?G05tr4n_@@uLjRNjj(
z#KtA`u^+L};|s*6#C+xrq2Y@V@$CiI99a1Bu!-HoS7ys|hY)(1)X507^IX>2bL|Ai
z-S&c)bLLv-HTZ&$(7OHk8Ko0$U39~JW3Ahr!=SVxHIC6
z==%5%Eu*&x$h;mr?R9?O8qtXTOxYQ~r%aMONctAtg+7LdPy6BRCD&yA?Lf1Cv{^!7
z9#3v%5$Du4Www5i3(qFDG=C8a&yb;nMU61qW?}A&HN0Gd)v?RIIf)>m3*;(81LZ8Y
zg*W7?UQk0*nRa-ydcpbURWbZEHcxxz;&HLuC6zt>qG>7*u8Mo!Bn3pa=;Ae>Atg`p
z!FDqp)MYYRsNQ=kcjZIuD+n3yA9!@M4aU6L(!8$40=%f
z2zp@rthXVoqlyohRFmpijRPEw
z8jQ`*vr$J5l+m|(>NBH^rG`gbSd+R{W7!q)rnj9;Jwt1hemj*HR6fz?3(e1YBA@zC
zs#nB|gxDz(JFZt9V{KBZG$lEdCK5w4VpBgi7_bS}9*@6P6j*mSjHvF~Lvont%0ix@
zOSkyRu$P$g!=rg#sHmKqhBuJacWawAE|nLv6uon%en)*N#cg
zfNc|P;fvajAmrshSZnO_dZIi*?e_c-)LFPiqUTwwkbB!*qD9fVM$}u!MPiS-CTz6_
z_#6ZN(NgV?ZQR8*9XsDIXU{BEXYF-0m!HP`1LKMMFkXRDT~o{
zHB7y20@F*Ha0Z6@`;#N~ke$`)wKJ`@&2cw*hemBG&Q=AkD%QKGt{v_P^%1H|{o8ab
zm|vN}Jd7!lFW9}_5MNI*&>Xs#d<#dHJPTo-NT+$$USrfL?G;g;Nt|ck(u2EP1%6&!
zo{;-ASs)8h_SDjCvpBNqDfG-y#ux-rKDuv~8Vfj`w5#gni6MRlhddr2*>{JRV2g=@
za*){y1I>WcF|cm4>A^_%1;u2OTK+kguw6+xS%o6R+<``1Pj1NshmHUT8)*DXVNP
zjuQguTO8}Ln+Pq=peVN2)&AO0IB;)kAf!Ua#uYo@dJq6~nuTC~Fz{mmbf(1M^BU-{
zOD52SfR3^!>Xew_9qfM++|DS>Us_pFE0ovO_2E;iBoY=ni_b1MW?LCGtyt}k9P$g3
z+H}28W)A4f$Nxf}>gehuADR`=VyOCM(vCd%ODERE0j=m6uv}*k_D#s~!4CS{T)5}A
z`x$$j9!}|_5?o48SkO8I5C#D1=X@`Whu;OneXg(vN;v~_5VIoKB!aO=)NK$~-9nyb
z@{at^{-IaMfRb&Wu7N@>RUi01mi(owCK1&aZQ){mYWoB4C&Wc9RWjg@Rh4s9S3MBeae)pF@J*UC?1lJpeux>g(^`G;JsyAk*S+2PK
z_Ya~Q;-Gi@^R9-{2Fu)D+y^#+v79OBb6mdFngbr|F&aF_Puv;k^{x
zuQSvFi+c^wc}&|(A7}XyP#=IVpsiMWL{P0nz9g;4UTanqk);nHJMK67DRNP6Z*B*=
zke_8A#sMb0d@`}kw?4wF*a66`p9EL@AanE_>PxxZNW7bHu}(z{n+2e-Kny^
zYj#>3zHkdUzw`r0tL>o|b~uZa09#q+8yH-C$6;9X^e*6t?!@@uBzqGKIt`5D3sCEeLLPq?q&k$otcNg+1
zLczAL<>*n47*BuCknpVb(-*F26Y73hy7S+bD8n3iwV
z2h*>@H?^;zo6E3QZ<3GxgpY3{A8;cdIQv_VA2j}0=H7Y(1ov>s5ggQKrq4t4*JnQw
ze@jl__;@O(v$WS!lbB7|Boo8;lb^7p1rl-Rz&ll^?cmII$x8QdQ2Q^DQ~R%q`Q8OK
zYG301F>tm{_6WmNQ`ls`w|u8FIj!wq_9q+n`zFvYlWf}^6#PVc->hHg_mIgp%#ah8w)r-z
zZs%UBGV+~e3yi=`|MQ+Mlz;=d=~h5u_{ls4L|arv&a*udJ=E-zS`ig?5$dEme}7dH|KY#7#)3Lz|86qC7}08xKr
zmx2~(ZY$-bK3?Ko+X|ng$GGnD%O|g^IDgZRxR3Dz_YU5AumkkQ&)$M1Zb{rg6|Y3+
z1z5MdqlMq$WmNnH&3vIw3v}*alYOzaN&H8fiW>ne`^_5&_lFM${VpfjNLIJGiW5-Z
zan>=*Gm4fklU(Y;4wipUMF?9f>d@^c`1z}QEw7)SJK7J$Qcozed-S6i^-c!iUGTr_
zjFy*&F%CZC#I%_I-|o!+O=raNzqKK0o<1rIn8VZA2a~cl=t?9#1{&f&%|=5Yg@acc
zz95@eql*AoWPfoQ8n9xRQGQiH(9%k&C|hXDQ?stdZ<;yX4qKgUrj3v}KLs{5RX4pg
zzTGJco|hi2d)|6@wu%z<_XwKXnO(F$zPxOFy8SURy;;bSDl1qBu?I=J*r*X7w8XZ)C^RE=7cP-Dw3{4!rOqdJ5=Nu#6k?#dZ
z5>cR`P$+lqkOOh$L!OfdK@sROlSAcabfIsn82LH((gku-HY(_daqP*fpk4X)o1_P6Ta`ATt3#UA(;#36mki7iY%f2{BVke%!Y)M`2?
zE5=5cbA=UlipVuiM=~HVM7T9$Ek6*FVzH9EL8^;kdVqRc;#krQGs1p(H!uV}&PFMT
z%FYfO%b}AqEvvq(%fVUt+JUQl8<={QG1%rJNP+MCscw`ePhmj7d~&DtZ&g
zbnCIxTs&pB!*qXtr)}GnnMm~eWv?^w>X5$cm`9WHkm+!FMLdJVi@9Gw@l_eND+I`J
zN5TtyxcryFgvM{9rCVRY=qx+ZDXk(!qgj0rlz);xt762wh{3b!m=zJ|6*u}YLEp_I
zXKDXBoA$m4;MW%)z60fKWGYLuhDVQkY|++#6M-R}3;E5UctmWpD(kF^n`P~18-kH?
zM^nz&HtQ`~j`qx^f1H$V-9^srQuHTO6%+w|?czEB*VYG8Al9R^@LmZMrl{B4D5!TJ
zfJ2R94y{PtRla{hBRnZm6_i%Qzm(BsP7GTtU0~}%GVfgh2#gy%kFYcB!kRq6+x*T)
z%`s;dzxydeniIuzIBWVu^BU7PZR!E3H_$&!Z3QwQj~Y%wV(JyfMd=-%zh(|qr|yv6
zVaL@A$EG1Dxk3n4r|Ae=#Dz;Xgr6V1LR^-L?-Jfg1^9{YEU~`A`pN9L12&7Uek0lU
z^8z-DuZTh)O}U`XOrCrxeMtJ%mKpoQui&h7fz^Ua)^JS%zjoxW%yHkLh{vzgpTxqt
zd#R90VlAi`;Y;HOpzkNO&PNOyNW$?r&v>{Uc*N=C}jQbBF3My^VPaWk&t`wc^CD9+ia
zR$Wa7zl9M+^HikrGP%qInyk>lx)Y@~uo&Mrwa$jF(}Rx)wxo-aF#~RHljDO>S{x77
zSXPxjq~B?x#N}*^xJr2aY;}D)5Iw1STo{KtM?SCPP#kHIwpEcVi@Ti8S4lgi8-IwG
z1vX6~he%()q{VEM_HZx%`jNe@!xfJjb>GM%#1AwXln)<1TSLX#LrWnM{!AyaD#_&e
z(j)+f2(ClX_!3>;5>2b^x@^mZd;jPyu{LWU*s{w=U4B(0+;G2%thDl%U$1glD-qT_
zbLp_Wu39R%agX(745JXQp6FY7q<>*nF>dAu!37vMjdwm
z=y+K4$OpB;`qu54vs>Mj=9euVHuIy-#05*NAd{c7QEN%fwavQ-p^HR#L2l*T&kk3d1UL?Zv(FG-(v3^P}6bx1E`yQ7=nw
z*|jKY3!~on`J-a-qWO&LoCoM_Hx-?Sqb7`7HPkAab=xuV7tb8or7Vj*Yq?Kb%;tcB
zw0Vab*XV_LH^oSQ{N~mbqH`snixRXXar8l
zk9_j*)h$Nf3ite1G)!TSro>G`fxZ<%>G1DxwbP5|KSh*fPI&6Zd^m{3DFwe
z(>!sNi4T5ZNjvrgP;SDyH81V`t`crBL7e^d_uP`JTFps@$M+X7mwc8po8Cw-;eQbJ
z4#1fNf4^^R+u7K*ZQHi(Y>bU<+j^30%qO;Ob7N<-H~;gVTc^%jb>CanJySI`RZ~+v
z-90~jzM069Y(niiAc|%pFpV9|8PlPfnl+1?_2&+ejv7vUkCo#~Gi||XZPE>KZPH9-
zis-9!h>M$kq`q|bi(LdyoP|4*OPjI2dMZx%7Y4z;O#DbasrjQdS}IQgu{ks01$p`n
zDVH8diCc^w=LQqw9+TM5~Rl{}zs+Hf
zxMvuxz46#8n#!=J>JZtdVgT?wcZxTbKAU)5oopRl`k6dgAlw`}@u~xLoK@(0lA<%`zxYB>Z3xTBPeTk2|((mWLO7YnjBm+`UC>3&H&JnA*KDG@^Ds-{Dm=zN-LJwvSk>5Jb^2@F)qyqX;VRZ
z?OrM%=A{G4u~8_AzhoUs%h0NN;X)WDVxJTvXu^UP8CM;`rw++si5c6h(!sGfCWQSq
zEB@s(7KnAvG^PS-`DVxdh36loKmBIs&4}JACEWwdS+f+nR`7gIU+hS3T@bWxh4_9p
zm}wDK2i|2tld3Zld6({6*~otOCB-5anm7DUZ{RlSoM6u?)2W+(naAk?KG{
zjJw8dua+3}6rOel=}Jsz@6gWnyP?<7^aju6j4rXO<7TZK_)0nptnT|tx(FP0n(b7u
zytO<%4p{gLP-N2h@2g&}dvre3&k+P)m~CI2?Tt`Jfe_plrqQTIb!SrhMa3{lL*HXw
z)Zc@cqxW?iXPb*>o1l-^>!?4wAbQOg+6bvm^!m>><<2%m9NjRIS!^JyCxW>sN4H;}}Ndd;xk3u))EW6k4T@S1*OzyGc){`SBdkd^dd
zIHcSxwx1nJ&5r`^_=hKn;EzNq7e@RfpFV->yyaZC$}BFDMDC@$#{>slxcS__Lbcmh
z>wc*P_)ux!H13uj3)iM8b*KJ_#G6~EecYzvD*jUYj*7Js|MIwyF}{l^;-$})Xr770
zF>*UQ18bi1ZT6%T#B>QYGGW{rj?Wa?sPbQ@RW|mn!J_U1@#a!n-y$0UxpxcgJWsdH
z7w;bh?A2X<|r`|IrXN*wXv$_AS6_!O$^g>TuK}ekN!-ypnJEnjnW)6h2
z53gT5hFycIH%&2|G}s#H=>yS&HKqf#rwC#I>-LAcg|o1Pn=9p5v5K1=3y_DKt(u0e
zmJXoL#4v$Ct(oZiZ(0fOUn4d)-yjgF?=O$>|C8PDAH0;PiJJwvq>Y8W`Trr=#Hq+B
zfw7=`P1M)+)Bb`J^v?3`=ScEi@lFggM=yp(cmcRKnV(Z`4u}4m0B5=Tk4OS;Ma_I@
z)ZN^<`@2B-V%tlG7Rc!tMv_!d5XV(kqtjq;XhbMwXx*zQvwEc4SHB;sR`U+ELTR=E
z^U)#m5~+o;AZV*Ux$&1OZI&U+Qdb{MZy+nBxlleDfIn4siyj+2Y3oiVHEReoVT3>F
z@4xFaAs$np5;3*AFM(98nzVkl9h4m7W*N`&!EL^{0Q5k>IBGJ%|;oFU}
z7ZxZ!8-2BvW#0Rgd^J)Q{NBxZ<<%$4M*$Y
z-{cl;nEwGf^uL&3{~5IZS|{>SuU!`-UX(Vc6!`)X=(4w(PY7SimhaoaiF
z-fs5&*sb9LnK|f<8nB&Bp=m=7<@t7NH+;80bC;eF&`h%!a
z%=BbC<9}d_g#*?7;}1)Y{${EGN7jj6oRR5#36=x2lk_<})tSmZD6Tc{Mt@m8(r-e)
zfH&Hzxsi=0a;F_N39j}u4_yh@E3qUKB`+T5*nON)4gxlpypm{0OrOw_h#Um7t}4`c
zJ?iZCX%}cOoYa}qJ#Ml$B+6|vDbQ9pW5
zCL<0PM;iED3%E^Gr^55<#~OL#EcwGcMw+gVtMk$1(Jn!A8
zQk!bWmNjrIMeW;kQ!Whccls6QW>ntr%EIp`4ym8#3X}w}GI_OZUluFnog{C1
zqYxYWDpLkPZ9h`RdvMCry})iEk-(sUB>pmH;E^umm_CYk7uY=Scv;6Ok&1squgq*?
z`{vt%zp$BCnQ(w3@Y?nQ^Sr{H;51djvi&yMJYw%DI0NdU-P_9)a8IAw0bobsMIObs&gL0vc*nd=jqH||~VX1-a
zg7N<=iD7Pz>*olz16zfthy4a5f5?q_fYS=l?_*qhK|6CnYSS23>wUd*`p8Y{>FzAt
zr>8S5s(2n{sJ(rbe>yS8?V6Z(v2eAS+~cLJW_FJpah%X=$U#4lRaH(M*xer20dWSc
zcA%hEyR=_^H$`V_EY%iUVybCI*s9v(0#SM#qG{(mHsJreb97YeXdCpK?bn0^0z&gY
zuDw#OP9Dx`?k4X4HJ8)0w%yP*FofC^QWO9Vi>eT^G(Xfgi!qe%z{MBX6}~TL+UphC
zZk6YtNqdebcaRMu
zzwA~YBp-SI+mQ*6VMzXN4x$K)0^fg*;yxe;HUudR!%P`O-ro*_4n_`{iSdI%ST{%>
z#L&`tvl2ro{-|t8+TTbpNkPftzUs_87c>Q@WyHPCls22EF15y%jR+LSod?rZH=gn#
z1;{>%Q|mkvXL;!2R~>(uPLDpej<5UQpJjrE+qz{#X>
z#x6iUoo!MkV3l+}lU{+32+g>0fQL9|!t#)YM<^xj$XgJ5R&lgBm5TYyMF^n{Ep7C|
z4ieYiek==*C<(CQFNi*S?=Fkbfo6x?Dv+Ff*Uc^(Wde0QoUEJQFxFX>>Q;708`?N5
zjwr@6@`GDedLfz@TxEfM`Bz$+tVA928f(r{TzHYFL<1hAM`fk@)SIaVwH4lS2v4p0
z()8qpLHk@tkyb)!s)WC|)qNtM6d?`MA$UP<1B?
z)?|7S0Vo`KthPKTMP%y?uH2S1EB6^P9h4oQXIKXC!D|4OIow95vuqVP($zyn@S~Pu
zO^IqPG^*VmC_+nOZRg|-Xdk9iC#u;K{I(1hWKW2orvHL3BKWiXBtl-zr?;`K?&Pk(
z1F&kHj4s2=`slLAhB+))5z!Y#{p7l37KuNW9~So-f?OU<4>kA;Zb%ftELXq&s|$~6
zSEKpF5MP1s+Fpuub&ooloQ~z9rM@oTnrBmo>cX=@ob_biB{J`-CCk-~NRe;Fnwd{~
z!0mQI{P4pnk^<0egQT)ZpFh-q9g}I|V83LrIQU0&JwU67pe;LH0^dN=i9$)j8v{T(
zWGo)W9UGlk$Sf%mB8ZxdF+wA+oLQP!oLHV%bPKbW&bd95gSn6Ctr51m7Yow>)Iog~
zCJz0|`CE@u`yxAy(^)n8I4ogM0_+|rd>Ns;XNt1@Wi*LUY<@c(xSijMLw`AW>CiR&
z)aV$VyiM+C5C_>^{qLPYMw_(}b#sHV`@ORWnp2F}vw*KMr$6u42cb8}T_L!Wh<^t7
zZk%@wI5Nr3N&hD5jq{!#%I;m
zpy~WQi%EjnGxeQ6@iHSZ)fJ0PLdtU{V6;WR@)c*m>M$~xCDIy3O47jfmbFpoHQoFo
zGB>s#V;4s$$R=~&A%OU*Pw|t6JkeWtM8g7{{aJf``|@j7*fe)jNz+a
zjsJ!QscZODV7R(M+dW3;1p`}PxX$rTEB^qpmY>lQJX0!A&w!9%Yrze4BiqX#DoJk6
zT#R@yUT)4Fhz0*{f7WIkg9r}8#}vF95dsN`FZqduw9=SIRB6H|qz)8;kF?`9H))Ch
zVma0Y&hQmsen+{j0^oaY33q&V4;dc8cL;AK