From d2598ca63a3a4d390b60f0092c0e894274fa41d7 Mon Sep 17 00:00:00 2001 From: quanwan Date: Wed, 17 Apr 2019 10:18:43 +0800 Subject: [PATCH 01/15] dpark conf --- conf/gateway.conf | 4 +- conf/gateway.conf.0314 | 114 ++++++++++++++++++++++++++++++++ conf/gateway.conf.0318 | 121 ++++++++++++++++++++++++++++++++++ conf/gateway.conf.bak0319 | 133 ++++++++++++++++++++++++++++++++++++++ db/gateway.db | Bin 73728 -> 86016 bytes loadconfig.go | 13 ++++ tcpserver.go | 4 +- worker.go | 24 +++++-- 8 files changed, 403 insertions(+), 10 deletions(-) create mode 100644 conf/gateway.conf.0314 create mode 100644 conf/gateway.conf.0318 create mode 100644 conf/gateway.conf.bak0319 diff --git a/conf/gateway.conf b/conf/gateway.conf index 196af62..2346668 100644 --- a/conf/gateway.conf +++ b/conf/gateway.conf @@ -109,10 +109,10 @@ }, { "adrh":0, - "adrl":0, + "adrl":1, "type":0, "version":"yunhorn_ys_l_v1", - "flip":false, + "flip":true, "id":"018B5704-55BE-40CA-9D3E-90EF157C2489" } ], diff --git a/conf/gateway.conf.0314 b/conf/gateway.conf.0314 new file mode 100644 index 0000000..750223d --- /dev/null +++ b/conf/gateway.conf.0314 @@ -0,0 +1,114 @@ +{ + "gateway_info": { + "id": "F23FACD2-7D85-4FCC-88E3-C5B78931A26D", + "version": "yunhorn_gw_c_v1", + "location": [113.960347, 22.54143], + "单位": "深圳市云兴科技", + "config": [{ + "id": "EC13C2D9-6A93-4894-BB5B-89BDAA786D8A", + "version": "yunhorn_kgl_c8_v1", + "data": [ + ["男厕位", 1], + ["男厕位", 2], + ["男厕位", 3], + ["男厕位", 4], + ["男厕位", 5], + ["男厕位", 6], + ["男厕位", 7], + ["男厕位", 8] + ] + }, { + "id": "82BF7B5E-EC0D-4DB6-807F-B097C3C84073", + "version": "yunhorn_kgl_c8_v1", + "data": [ + ["母婴", 1], + ["残卫", 1], + ["残卫", 2], + ["男便池", 4], + ["男便池", 5], + ["男便池", 6], + ["男便池", 7], + ["男便池", 8] + ] + }, { + "id": "F5B7FDCC-79A8-499E-A925-F2FF357BE30D", + "version": "yunhorn_kgl_c8_v1", + "data": [ + ["男厕位", 9], + ["男厕位", 10], + ["女厕位", 14], + ["女厕位", 15], + ["女厕位", 16], + ["女厕位", 17], + ["女厕位", 18], + [null, null] + ] + }, + { + "id": "00DD66A6-378E-450D-98AA-44AC02741980", + "version": "yunhorn_kgl_c16_v1", + "data": [ + ["女厕位", 1], + ["女厕位", 2], + ["女厕位", 3], + ["女厕位", 4], + ["女厕位", 5], + ["女厕位", 6], + ["女厕位", 7], + ["女厕位", 8], + ["女厕位", 9], + ["女厕位", 10], + ["女厕位", 11], + ["女厕位", 12], + ["女厕位", 13], + ["男便池", 1], + ["男便池", 2], + ["男便池", 3] + ] + }, + { + "id": "4E5D52DD-EB81-43C0-A2B6-04E432412EBA", + "version": "yunhorn_kgl_l_v1", + "data": [ + ["纸巾卷", 1] + ] + } + ] + }, + "devices_list": [ + ["15394892-E8B0-4FF2-BC35-1BF380BD1B68", "port1", "yunhorn_xsy_l_v1", "1"] + ], + "serialports_list": { + "port1": { + "com": "/dev/ttyUSB0", + "bauds": 9600, + "size": 8, + "parity": "N", + "stopbits": 1, + "readtimeout": 1000, + "note": "液位" + } + }, + "rs485devices": { + "15394892-E8B0-4FF2-BC35-1BF380BD1B68": { + "version": "yunhorn_xsy_l_v1", + "num": "1", + "command": [ + [8, 3, 0, 1, 0, 2, 149, 82] + ] + } + }, + "loradevices_list": { + "4E5D52DD-EB81-43C0-A2B6-04E432412EBA": { + "version": "yunhorn_zjj_l_v1", + "num": "1", + "command": [ + [85, 2, 242, 170] + ] + } + }, + "iconurl": "http://192.168.3.188/icons/", + "websocketurl": ["192.168.3.216:8080", "/echo"], + "post_to_server": "https://smartoilets.cn/socketServer/statis/push", + "debug": true +} diff --git a/conf/gateway.conf.0318 b/conf/gateway.conf.0318 new file mode 100644 index 0000000..b5712da --- /dev/null +++ b/conf/gateway.conf.0318 @@ -0,0 +1,121 @@ +{ + "gateway_info": { + "id": "F23FACD2-7D85-4FCC-88E3-C5B78931A26D", + "version": "yunhorn_gw_c_v1", + "location": [113.960347, 22.54143], + "单位": "深圳市云兴科技", + "config": [{ + "id": "EC13C2D9-6A93-4894-BB5B-89BDAA786D8A", + "version": "yunhorn_kgl_c8_v1", + "data": [ + ["男厕位", 1], + ["男厕位", 2], + ["男厕位", 3], + ["男厕位", 4], + ["男厕位", 5], + ["男厕位", 6], + ["男厕位", 7], + ["男厕位", 8] + ] + }, { + "id": "82BF7B5E-EC0D-4DB6-807F-B097C3C84073", + "version": "yunhorn_kgl_c8_v1", + "data": [ + ["母婴", 1], + ["残卫", 1], + ["残卫", 2], + ["男便池", 4], + ["男便池", 5], + ["男便池", 6], + ["男便池", 7], + ["男便池", 8] + ] + }, { + "id": "F5B7FDCC-79A8-499E-A925-F2FF357BE30D", + "version": "yunhorn_kgl_c8_v1", + "data": [ + ["男厕位", 9], + ["男厕位", 10], + ["女厕位", 14], + ["女厕位", 15], + ["女厕位", 16], + ["女厕位", 17], + ["女厕位", 18], + [null, null] + ] + }, + { + "id": "00DD66A6-378E-450D-98AA-44AC02741980", + "version": "yunhorn_kgl_c16_v1", + "data": [ + ["女厕位", 1], + ["女厕位", 2], + ["女厕位", 3], + ["女厕位", 4], + ["女厕位", 5], + ["女厕位", 6], + ["女厕位", 7], + ["女厕位", 8], + ["女厕位", 9], + ["女厕位", 10], + ["女厕位", 11], + ["女厕位", 12], + ["女厕位", 13], + ["男便池", 1], + ["男便池", 2], + ["男便池", 3] + ] + }, + { + "id": "4E5D52DD-EB81-43C0-A2B6-04E432412EBA", + "version": "yunhorn_kgl_l_v1", + "data": [ + ["纸巾卷", 1] + ] + } + ] + }, + "devices_list": [ + ["00DD66A6-378E-450D-98AA-44AC02741980", "port2", "yunhorn_kgl_c16_v1", "1"] + ], + "serialports_list": { + "port2": { + "com": "/dev/ttyUSB1", + "bauds": 9600, + "size": 8, + "parity": "N", + "stopbits": 1, + "readtimeout": 1000, + "note": "液位" + } + }, + "rs485devices": { + "15394892-E8B0-4FF2-BC35-1BF380BD1B68": { + "version": "yunhorn_xsy_l_v1", + "num": "1", + "command": [ + [8, 3, 0, 1, 0, 2, 149, 82] + ] + }, + "00DD66A6-378E-450D-98AA-44AC02741980": { + "version": "yunhorn_kgl_c16_v1", + "num": "1", + "command": [ + [3, 2, 0, 0, 0, 16, 120, 36] + ] + } + }, + "loradevices_list": { + "4E5D52DD-EB81-43C0-A2B6-04E432412EBA": { + "version": "yunhorn_zjj_l_v1", + "num": "1", + "command": [ + [85, 2, 242, 170] + ] + } + }, + "iconurl": "http://192.168.3.188/icons/", + "websocketurl": ["192.168.3.216:8080", "/echo"], + "post_to_server": "https://smartoilets.cn/socketServer/statis/push", + "debug": true +} diff --git a/conf/gateway.conf.bak0319 b/conf/gateway.conf.bak0319 new file mode 100644 index 0000000..2394e26 --- /dev/null +++ b/conf/gateway.conf.bak0319 @@ -0,0 +1,133 @@ +{ + "gateway_info": { + "id": "F23FACD2-7D85-4FCC-88E3-C5B78931A26D", + "version": "yunhorn_gw_c_v1", + "location": [113.960347, 22.54143], + "单位": "深圳市云兴科技", + "config": [{ + "id": "EC13C2D9-6A93-4894-BB5B-89BDAA786D8A", + "version": "yunhorn_kgl_c8_v1", + "data": [ + ["男厕位", 1], + ["男厕位", 2], + ["男厕位", 3], + ["男厕位", 4], + ["男厕位", 5], + ["男厕位", 6], + ["男厕位", 7], + ["男厕位", 8] + ] + }, { + "id": "82BF7B5E-EC0D-4DB6-807F-B097C3C84073", + "version": "yunhorn_kgl_c8_v1", + "data": [ + ["母婴", 1], + ["残卫", 1], + ["残卫", 2], + ["男便池", 4], + ["男便池", 5], + ["男便池", 6], + ["男便池", 7], + ["男便池", 8] + ] + }, { + "id": "F5B7FDCC-79A8-499E-A925-F2FF357BE30D", + "version": "yunhorn_kgl_c8_v1", + "data": [ + ["男厕位", 9], + ["男厕位", 10], + ["女厕位", 14], + ["女厕位", 15], + ["女厕位", 16], + ["女厕位", 17], + ["女厕位", 18], + [null, null] + ] + }, + { + "id": "00DD66A6-378E-450D-98AA-44AC02741980", + "version": "yunhorn_kgl_c16_v1", + "data": [ + ["女厕位", 1], + ["女厕位", 2], + ["女厕位", 3], + ["女厕位", 4], + ["女厕位", 5], + ["女厕位", 6], + ["女厕位", 7], + ["女厕位", 8], + ["女厕位", 9], + ["女厕位", 10], + ["女厕位", 11], + ["女厕位", 12], + ["女厕位", 13], + ["男便池", 1], + ["纸巾卷", 2], + ["男便池", 3] + ] + }, + { + "id": "4E5D52DD-EB81-43C0-A2B6-04E432412EBA", + "version": "yunhorn_kgl_l_v1", + "data": [ + ["纸巾卷", 1] + ] + } + ] + }, + "devices_list": [ + ["00DD66A6-378E-450D-98AA-44AC02741980", "port2", "yunhorn_kgl_c16_v1", "1"], + ["15394892-E8B0-4FF2-BC35-1BF380BD1B68", "port1", "yunhorn_xsy_l_v1", "1"] + ], + "serialports_list": { + "port1": { + "com": "/dev/ttyUSB0", + "bauds": 9600, + "size": 8, + "parity": "N", + "stopbits": 1, + "readtimeout": 1000, + "note": "液位" + }, + "port2": { + "com": "/dev/ttyUSB1", + "bauds": 9600, + "size": 8, + "parity": "N", + "stopbits": 1, + "readtimeout": 1000, + "note": "液位" + } + }, + + "rs485devices": { + "15394892-E8B0-4FF2-BC35-1BF380BD1B68": { + "version": "yunhorn_xsy_l_v1", + "num": "1", + "command": [ + [8, 3, 0, 1, 0, 2, 149, 82] + ] + }, + "00DD66A6-378E-450D-98AA-44AC02741980": { + "version": "yunhorn_kgl_c16_v1", + "num": "1", + "command": [ + [3, 2, 0, 0, 0, 16, 120, 36] + ] + } + }, + "loradevices_list": { + "4E5D52DD-EB81-43C0-A2B6-04E432412EBA": { + "version": "yunhorn_zjj_l_v1", + "num": "1", + "command": [ + [85, 2, 242, 170] + ] + } + }, + "iconurl": "http://192.168.3.167/icons/", + "websocketurl": ["192.168.3.216:8080", "/echo"], + "post_to_server": "https://smartoilets.cn/socketServer/statis/push", + "debug": true, + "openserial":false +} diff --git a/db/gateway.db b/db/gateway.db index 215fc0adb5e3c7805beb240da3dfabafe7b3d686..d6201664b8ee59db22c5fd603cddb613a83e8f1c 100644 GIT binary patch literal 86016 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 MsLbIj)CKl`0Z%iF?f?J) literal 73728 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 Date: Wed, 17 Apr 2019 18:57:44 +0800 Subject: [PATCH 02/15] =?UTF-8?q?=E5=AE=8C=E5=96=84dpark=E6=BC=94=E7=A4=BA?= =?UTF-8?q?v2,=E5=BC=80=E5=8F=91=E6=95=B0=E6=8D=AE=E6=8E=A5=E6=94=B6?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=BB=A5=E5=8F=8A=E6=8E=A8=E9=80=81=E5=88=B0?= =?UTF-8?q?=E4=BA=91=E7=AB=AF,=E5=AE=9A=E6=97=B610s=E6=8B=89=E5=8F=96?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=98=B2=E6=8A=96=E9=85=8D=E7=BD=AE=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/gateway.conf | 122 ++------------- loadconfig.go | 45 ++++-- main.go | 6 + router.go | 373 ++++++++++++++++++++++++++++++++++++++++++---- worker.go | 2 +- 5 files changed, 393 insertions(+), 155 deletions(-) diff --git a/conf/gateway.conf b/conf/gateway.conf index 2346668..c2573a1 100644 --- a/conf/gateway.conf +++ b/conf/gateway.conf @@ -6,86 +6,18 @@ "单位": "深圳市云兴科技", "config": [ { - "id": "deb03e28-ddcb-4e5d-aa31-d870a1f0f09b", + "id": "8E146028-E1B1-4AC9-8F47-01376A22CB35", "version": "yunhorn_kgl_c8_v1", "data": [ - ["女厕位", 1], - ["女厕位", 2], - ["女厕位", 3], - ["女厕位", 4], - ["女厕位", 5], - ["女厕位", 6], - ["男厕位", 1], - ["男厕位", 2] + ["女厕位", 1] ] }, { - "id": "EC13C2D9-6A93-4894-BB5B-89BDAA786D8A", + "id": "7BB22E6A-ED0D-4161-8370-6B722D3683B7", "version": "yunhorn_kgl_c8_v1", "data": [ - ["男厕位", 7], - ["男厕位", 8], - ["男厕位", 3], - ["男厕位", 4], - ["男厕位", 5], - ["男厕位", 6], - ["纸巾卷", 7], - ["纸巾抽", 8] - ] - }, { - "id": "82BF7B5E-EC0D-4DB6-807F-B097C3C84073", - "version": "yunhorn_kgl_c8_v1", - "data": [ - ["母婴", 1], - ["残卫", 1], - ["残卫", 2], - ["男便池", 4], - ["男便池", 5], - ["男便池", 6], - ["男便池", 7], - ["男便池", 8] - ] - }, { - "id": "F5B7FDCC-79A8-499E-A925-F2FF357BE30D", - "version": "yunhorn_kgl_c8_v1", - "data": [ - ["男厕位", 9], - ["男厕位", 10], - ["女厕位", 14], - ["女厕位", 15], - ["女厕位", 16], - ["女厕位", 17], - ["女厕位", 18], - [null, null] - ] - }, - { - "id": "00DD66A6-378E-450D-98AA-44AC02741980", - "version": "yunhorn_kgl_c16_v1", - "data": [ - ["女厕位", 1], - ["女厕位", 2], - ["女厕位", 3], - ["女厕位", 4], - ["女厕位", 5], - ["女厕位", 6], - ["女厕位", 7], - ["女厕位", 8], - ["女厕位", 9], - ["女厕位", 10], - ["女厕位", 11], - ["女厕位", 12], - ["女厕位", 13], - ["男便池", 1], - ["男便池", 2], - ["男便池", 3] - ] - }, - { - "id": "4E5D52DD-EB81-43C0-A2B6-04E432412EBA", - "version": "yunhorn_kgl_l_v1", - "data": [ - ["纸巾卷", 1] + ["男厕位", 1], + ["男厕位", 2] ] } ] @@ -118,8 +50,9 @@ ], "devices_list": [ ["4E5D52DD-EB81-43C0-A2B6-04E432412EBA", "loraport", "yunhorn_kgl_l_v1", "1"], - ["EB5B0798-9B7F-474E-AAB8-467FD5FE1293", "loraport", "yunhorn_kgl_l_v1", "2"], - ["deb03e28-ddcb-4e5d-aa31-d870a1f0f09b", "loraport", "yunhorn_kgl_c8_v1", "1"] + ["deb03e28-ddcb-4e5d-aa31-d870a1f0f09b", "loraport", "yunhorn_kgl_c8_v1", "1"], + ["7BB22E6A-ED0D-4161-8370-6B722D3683B7", "loraport", "yunhorn_kgl_c8_v1", "2"], + ["8E146028-E1B1-4AC9-8F47-01376A22CB35", "loraport", "yunhorn_kgl_c8_v1", "3"] ], "serialports_list": { "loraport": { @@ -160,41 +93,6 @@ "command": [ [3, 2, 0, 0, 0, 16, 120, 36] ] - }, - "52A79B3D-D9D9-48AF-AEB4-7D456BA22B31": { - "version": "yunhorn_db_c_v1", - "num": "1", - "command": [ - [104, 65, 4, 0, 120, 16, 68, 104, 17, 4, 51, 51, 52, 51, 195, 22] - ] - }, - "607E11C4-8986-4F8E-807E-FFA655A6F677": { - "version": "yunhorn_sb_c_v1", - "num": "1", - "command": [ - [104, 16, 103, 19, 146, 128, 1, 0, 0, 1, 3, 31, 144, 2, 186, 22] - ] - }, - "066BB944-AFA2-4E5D-86FA-61D9080A97BB": { - "version": "yunhorn_kq_c_v1", - "num": "1", - "command": [ - [2, 3, 0, 0, 0, 7, 4, 59] - ] - }, - "22E175B2-8DD5-4740-B428-0297F409AA47": { - "version": "yunhorn_lhq_c_v1", - "num": "1", - "command": [ - [4, 3, 0, 6, 0, 1, 100, 94] - ] - }, - "20F44B9C-E4A1-478E-B28F-0B7B14A2AF64": { - "version": "yunhorn_aq_c_v1", - "num": "1", - "command": [ - [3, 3, 0, 0, 0, 1, 133, 232] - ] } }, "loradevices_list": { @@ -210,5 +108,7 @@ "websocketurl": ["192.168.3.216:8080", "/echo"], "post_to_server": "https://smartoilets.cn/socketServer/statis/push", "debug": true, - "openserial":false + "openserial":false, + "open_tcp_server":false, + "check_serial":true } diff --git a/loadconfig.go b/loadconfig.go index 81a4bcb..e93df7f 100644 --- a/loadconfig.go +++ b/loadconfig.go @@ -75,10 +75,16 @@ var conf Conf var DEVICEDATAS Devicedatas var demoDevice Device +var femaledemoDevice Device +var maledemoDevice Device + var db, _ = sql.Open("sqlite3", "./db/gateway.db") // 加载配置文件 func init() { + + time.Now() + configfile, err := os.Open("conf/gateway.conf") check(err) defer configfile.Close() @@ -115,17 +121,36 @@ func init() { log.Println("init demoDevice success:", demoDevice) var device2 Device - device2.Lock() - device2.ID = demoDevice.ID - device2.VERSION = demoDevice.VERSION - device2.ONLINE = demoDevice.ONLINE - device2.DATA = make(map[string]interface{}) + device2.Lock() + device2.ID = demoDevice.ID + device2.VERSION = demoDevice.VERSION + device2.ONLINE = demoDevice.ONLINE + device2.DATA = make(map[string]interface{}) - device2.DATA["data7"] = 0 - device2.DATA["data8"] = 0 - - device2.Unlock() - DEVICEDATAS.DATA[demoDevice.VERSION+"_1"] = device2 + device2.DATA["data7"] = 0 + device2.DATA["data8"] = 0 + + device2.Unlock() + //DEVICEDATAS.DATA[demoDevice.VERSION+"_1"] = device2 + + femaledemoDevice.ID = "8E146028-E1B1-4AC9-8F47-01376A22CB35" + femaledemoDevice.VERSION = "yunhorn_kgl_c8_v1" + femaledemoDevice.DATA = make(map[string]interface{}) + femaledemoDevice.ONLINE = true + femaledemoDevice.DATA["data1"] = 0 + + //3是男厕 + DEVICEDATAS.DATA[demoDevice.VERSION+"_3"] = femaledemoDevice + + //2是女厕 配置演示使用 + maledemoDevice.ID = "7BB22E6A-ED0D-4161-8370-6B722D3683B7" + maledemoDevice.VERSION = "yunhorn_kgl_c8_v1" + maledemoDevice.DATA = make(map[string]interface{}) + maledemoDevice.ONLINE = true + maledemoDevice.DATA["data1"] = 0 + maledemoDevice.DATA["data2"] = 0 + //3是男厕 + DEVICEDATAS.DATA[demoDevice.VERSION+"_2"] = maledemoDevice dbdata_init() diff --git a/main.go b/main.go index 6858c76..27406c1 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,8 @@ func main() { go serial_run() c := cron.New() send_data(1001) + //获取数据防抖处理时间 + go getConf() c.AddFunc("0, *, *, *, *, *", func() { send_data(1001) }) @@ -23,6 +25,10 @@ func main() { // log.Println(string(build_data(1001,devices))) }) + c.AddFunc("*/30, *, *, *, *, *", func() { + getConf() + }) + c.AddFunc("0, */10, *, *, *, *", savedata_cron) c.AddFunc("0, 0, 0, *, *, *", insertdata) c.AddFunc("0, 0, *, *, *, *", get_weather) diff --git a/router.go b/router.go index 76ed9d9..80968d0 100644 --- a/router.go +++ b/router.go @@ -1,13 +1,18 @@ package main import ( + "encoding/json" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" _ "github.com/mattn/go-sqlite3" + "io/ioutil" "log" "math" "net/http" "strconv" + "strings" + "sync" + "time" ) var router = gin.Default() @@ -27,47 +32,344 @@ func gw_router() { v1.GET("/stink", aq_api) v1.GET("/satisfaction", pj_api) v1.GET("/seat/:id", seat_api) - v1.GET("/test/:id", test_api) - v1.GET("/test2/:id", test_api2) + v1.POST("/push", push) + + v1.GET("/getConf") } router.Run(":10086") } -// 厕位占用api -func test_api(c *gin.Context) { - DEVICEDATAS.RLock() - //type_id := c.Param("id") - - var device Device - device.Lock() - device.ID = demoDevice.ID - device.VERSION = demoDevice.VERSION - device.ONLINE = demoDevice.ONLINE - device.DATA = make(map[string]interface{}) - device.DATA["data7"] = 1 - device.Unlock() - DEVICEDATAS.DATA[demoDevice.VERSION+"_1"] = device - - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"}) +type DparkConf struct { + ExtensionInTime int `json:"in"` + ExtensionOutTime int `json:"out"` } -// 厕位占用api -func test_api2(c *gin.Context) { - DEVICEDATAS.RLock() - //type_id := c.Param("id") +var dparkConf DparkConf - var device Device - device.Lock() - device.ID = demoDevice.ID - device.VERSION = demoDevice.VERSION - device.ONLINE = demoDevice.ONLINE - device.DATA = make(map[string]interface{}) - device.DATA["data7"] = 0 - device.Unlock() - DEVICEDATAS.DATA[demoDevice.VERSION+"_1"] = device +//获取数据防抖配置时间 +func getConf() { + resp, err := http.Get("http://localhost:8082/dpark/getConf") + if err != nil { + // handle error + log.Println("getConf.get.err", err) + return + } - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"}) + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + // handle error + log.Println("getConf.readData.err", err) + return + } + + if err := json.Unmarshal([]byte(body), &dparkConf); err == nil { + log.Println("yunhorndebug.getConf.success:", dparkConf) + } + + if dparkConf.ExtensionInTime == 0 && dparkConf.ExtensionOutTime == 0 { + return + } + + if dparkConf.ExtensionInTime < 0 { + dparkConf.ExtensionInTime = 0 + } + + if dparkConf.ExtensionOutTime < 0 { + dparkConf.ExtensionOutTime = 0 + } + + extensionInTime = dparkConf.ExtensionInTime + extensionOutTime = dparkConf.ExtensionOutTime + + check(err) + +} + +//距离有效判断 +var reactTof = 1650 + +//数据防抖 进入时间 +var extensionInTime = 6 + +//数据防抖 离开时间 +var extensionOutTime = 10 + +var oldData1 = "" + +var oldData2 = "" + +var oldData3 = "" + +var dataMap sync.Map + +//接收传感器push来的数据,解析并上传到云端 +func push(c *gin.Context) { + + nowtime := time.Now() + + data := c.PostForm("d") + + log.Println("yunhorndeug.push.data|", data) + + go pushCODE1007(data) + + alldata := strings.Split(data, "#") + + if len(alldata) != 2 { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"}) + return + } else { + + valuedata := strings.Split(alldata[1], "*") + + if len(valuedata) < 1 { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"}) + return + } + + dtype, error := strconv.Atoi(valuedata[0]) + if error != nil { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errtype"}) + return + } + + var nowTmpData = "1#0" + + if dtype == 1 { + if len(valuedata) != 3 { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "valuedata not 3"}) + return + } + addr, error := strconv.Atoi(alldata[0]) + if error != nil { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "erraddr"}) + return + } + cs2001, error := strconv.Atoi(valuedata[1]) + if error != nil { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errcs2001"}) + return + } + + tof, error := strconv.Atoi(valuedata[2]) + if error != nil { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errtof"}) + return + } + + if addr == 1 { + + if cs2001 == 1 || tof < 1650 { + nowTmpData = "1#1" + } + + if oldData1 != nowTmpData { + dataMap.Store(addr, nowtime) + if oldData1 == "" { + //为空 直接改变状态 + maledemoDevice.DATA["data1"] = 0 + if nowTmpData == "1#1" { + maledemoDevice.DATA["data1"] = 1 + } + changeData(2, maledemoDevice) + } + //存储状态 + oldData1 = nowTmpData + + } else { + oldDevDataTime, ok := dataMap.Load(addr) + if !ok { + log.Println("load time err", ok) + } + + if ok { + if oldDevDataTime != nil { + //log.Println("t2.Sub(t1)", nowtime.Sub(oldDevDataTime.(time.Time))) + + var duration = nowtime.Sub(oldDevDataTime.(time.Time)).Seconds() + var durationAsInt64 = int(duration) + + log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData1, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64) + + if nowTmpData == "1#0" { + if durationAsInt64 < extensionOutTime { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return + } + } else { + if durationAsInt64 < extensionInTime { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return + } + } + maledemoDevice.DATA["data1"] = 0 + if nowTmpData == "1#1" { + maledemoDevice.DATA["data1"] = 1 + } + + changeData(2, maledemoDevice) + dataMap.Delete(addr) + } + } + } + + } else if addr == 2 { + if cs2001 == 1 || tof < 1650 { + nowTmpData = "1#1" + } + + if oldData2 != nowTmpData { + dataMap.Store(addr, nowtime) + if oldData2 == "" { + //为空 直接改变状态 + maledemoDevice.DATA["data2"] = 0 + if nowTmpData == "1#1" { + maledemoDevice.DATA["data2"] = 1 + } + changeData(2, maledemoDevice) + } + //存储状态 + oldData2 = nowTmpData + + } else { + oldDevDataTime, ok := dataMap.Load(addr) + if !ok { + log.Println("load time err", ok) + } + + if ok { + if oldDevDataTime != nil { + //log.Println("t2.Sub(t1)", nowtime.Sub(oldDevDataTime.(time.Time))) + + var duration = nowtime.Sub(oldDevDataTime.(time.Time)).Seconds() + var durationAsInt64 = int(duration) + + log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData2, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64) + + if nowTmpData == "1#0" { + if durationAsInt64 < extensionInTime { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return + } + } else { + if durationAsInt64 < extensionOutTime { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return + } + } + maledemoDevice.DATA["data2"] = 0 + if nowTmpData == "1#1" { + maledemoDevice.DATA["data2"] = 1 + } + + changeData(2, maledemoDevice) + dataMap.Delete(addr) + } + } + } + } + + } else if dtype == 2 { + //吸顶传感器 没有距离数据 + if len(valuedata) != 2 { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "valuedata not 2,type2"}) + return + } + addr, error := strconv.Atoi(alldata[0]) + if error != nil { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "erraddr"}) + return + } + cs2001, error := strconv.Atoi(valuedata[1]) + if error != nil { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errcs2001"}) + return + } + + if cs2001 == 1 { + nowTmpData = "1#1" + } + + if oldData3 != nowTmpData { + dataMap.Store(addr, nowtime) + if oldData3 == "" { + //为空 直接改变状态 + femaledemoDevice.DATA["data1"] = 0 + if nowTmpData == "1#1" { + femaledemoDevice.DATA["data1"] = 1 + } + changeData(2, maledemoDevice) + } + //存储状态 + oldData3 = nowTmpData + + } else { + oldDevDataTime, ok := dataMap.Load(addr) + if !ok { + log.Println("load time err", ok) + } + + if ok { + if oldDevDataTime != nil { + //log.Println("t2.Sub(t1)", nowtime.Sub(oldDevDataTime.(time.Time))) + + var duration = nowtime.Sub(oldDevDataTime.(time.Time)).Seconds() + var durationAsInt64 = int(duration) + + var tof = 0 + + log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData3, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64) + + if nowTmpData == "1#0" { + if durationAsInt64 < extensionInTime { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return + } + } else { + if durationAsInt64 < extensionOutTime { + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return + } + } + + femaledemoDevice.DATA["data1"] = 0 + if nowTmpData == "1#1" { + femaledemoDevice.DATA["data1"] = 1 + } + changeData(3, femaledemoDevice) + dataMap.Delete(addr) + } + } + } + } + + } + + log.Println("data:", data) + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": data}) +} + +//发送code1007数据到云端 +func pushCODE1007(data string) { + + //resp, err := http.PostForm("https://smartoilets.cn/socketServer/static/push", + // url.Values{"d": {data}}) + + resp, err := http.Post("https://smartoilets.cn/socketServer/statis/push", + "application/x-www-form-urlencoded", + strings.NewReader("d="+data)) + if err != nil { + log.Print("yunhorndebug.pushCODE1007.err", err) + } + + defer resp.Body.Close() +} + +func changeData(num int, device Device) { + log.Println("device:", device) + DEVICEDATAS.DATA[demoDevice.VERSION+"_"+strconv.Itoa(num)] = device } type EventNotificationAlert struct { @@ -263,7 +565,9 @@ func seat_api(c *gin.Context) { // log.Println("data:", DEVICEDATAS.DATA[version+"_"+num].DATA) //} + log.Println("============================devicedatas.data:", DEVICEDATAS.DATA[version+"_"+num].DATA) if DEVICEDATAS.DATA[version+"_"+num].DATA["data"+strconv.Itoa(k+1)] != nil { + log.Println("==========================do.data:", DEVICEDATAS.DATA[version+"_"+num].DATA["data"+strconv.Itoa(k+1)]) j = append(j, DEVICEDATAS.DATA[version+"_"+num].DATA["data"+strconv.Itoa(k+1)]) } } @@ -271,7 +575,7 @@ func seat_api(c *gin.Context) { } } - //log.Println("end conf.data:", conf_data) + log.Println("end conf.data:", conf_data) switch type_id { case "1": @@ -313,6 +617,9 @@ func get_seat_device_data(id string) []string { // 从配置文件中匹配对应的数据 func scan_seat_from_confdata(T string, conf_data [][]interface{}) Seat_data { var data Seat_data + //实例化空集合 + data.POSITIONLIST = make([]interface{}, 0) + data.HASPERSONLIST = make([]interface{}, 0) for _, i := range conf_data { if i[0] == T { data.POSITIONLIST = append(data.POSITIONLIST, i[1]) diff --git a/worker.go b/worker.go index 342bd46..fe481a6 100644 --- a/worker.go +++ b/worker.go @@ -172,7 +172,7 @@ func yunhorn_ys_l_v1(data_buf []byte) { }else{ device.DATA["data7"] = 0 } - + //device.DATA["data7"] = data_int[0] device.Unlock() DEVICEDATAS.DATA[demoDevice.VERSION+"_1"].DATA["data7"] = device.DATA["data7"] From de99d7130e655567c8df7327f8ef47d0b2cf5463 Mon Sep 17 00:00:00 2001 From: fish Date: Wed, 17 Apr 2019 20:16:52 +0800 Subject: [PATCH 03/15] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E4=BF=AE=E6=94=B9=E4=B8=BA=E4=BA=91=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router.go b/router.go index 80968d0..b0e74fa 100644 --- a/router.go +++ b/router.go @@ -49,7 +49,7 @@ var dparkConf DparkConf //获取数据防抖配置时间 func getConf() { - resp, err := http.Get("http://localhost:8082/dpark/getConf") + resp, err := http.Get("https://smartoilets.cn/socketServer/dpark/getConf") if err != nil { // handle error log.Println("getConf.get.err", err) From 0f8c5e0b4cd5e1c8eef5be465bf2847c9bde8822 Mon Sep 17 00:00:00 2001 From: fish Date: Wed, 17 Apr 2019 20:53:42 +0800 Subject: [PATCH 04/15] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=BF=9B=E5=85=A5?= =?UTF-8?q?=E5=92=8C=E7=A6=BB=E5=BC=80=E5=88=A4=E6=96=AD=E7=9B=B8=E5=8F=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/router.go b/router.go index b0e74fa..779fade 100644 --- a/router.go +++ b/router.go @@ -249,12 +249,12 @@ func push(c *gin.Context) { log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData2, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64) if nowTmpData == "1#0" { - if durationAsInt64 < extensionInTime { + if durationAsInt64 < extensionOutTime { c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) return } } else { - if durationAsInt64 < extensionOutTime { + if durationAsInt64 < extensionInTime { c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) return } From 5505ba460ecf80b2800131c65f6b47693c73334d Mon Sep 17 00:00:00 2001 From: fish Date: Wed, 17 Apr 2019 20:53:53 +0800 Subject: [PATCH 05/15] =?UTF-8?q?fix=E8=BF=9B=E5=85=A5=E5=92=8C=E7=A6=BB?= =?UTF-8?q?=E5=BC=80=E5=88=A4=E6=96=AD=E5=8F=8D=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/router.go b/router.go index 779fade..3cf3720 100644 --- a/router.go +++ b/router.go @@ -323,12 +323,12 @@ func push(c *gin.Context) { log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData3, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64) if nowTmpData == "1#0" { - if durationAsInt64 < extensionInTime { + if durationAsInt64 < extensionOutTime { c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) return } } else { - if durationAsInt64 < extensionOutTime { + if durationAsInt64 < extensionInTime { c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) return } From 45307d6a0661afa165f07f47b351cba4e7a6f39d Mon Sep 17 00:00:00 2001 From: fish Date: Thu, 25 Apr 2019 21:55:22 +0800 Subject: [PATCH 06/15] =?UTF-8?q?=E5=AE=8C=E5=96=84tcp=E4=B8=8B=E8=A7=A3?= =?UTF-8?q?=E6=9E=90lora=E4=BC=A0=E8=BE=93=E6=9D=A5=E7=9A=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router.go | 384 ++++++++++++++++++++++++++++++++++++++++++++++----- tcpserver.go | 155 +++++++++++++++++---- 2 files changed, 473 insertions(+), 66 deletions(-) diff --git a/router.go b/router.go index 3cf3720..cfe6e3e 100644 --- a/router.go +++ b/router.go @@ -13,6 +13,7 @@ import ( "strings" "sync" "time" + "bytes" ) var router = gin.Default() @@ -33,10 +34,14 @@ func gw_router() { v1.GET("/satisfaction", pj_api) v1.GET("/seat/:id", seat_api) v1.POST("/push", push) + v1.POST("/pushv2", pushv2) v1.GET("/getConf") } + + + router.Run(":10086") } @@ -68,6 +73,10 @@ func getConf() { log.Println("yunhorndebug.getConf.success:", dparkConf) } + if err!=nil{ + return + } + if dparkConf.ExtensionInTime == 0 && dparkConf.ExtensionOutTime == 0 { return } @@ -83,7 +92,7 @@ func getConf() { extensionInTime = dparkConf.ExtensionInTime extensionOutTime = dparkConf.ExtensionOutTime - check(err) + // check(err) } @@ -107,56 +116,70 @@ var dataMap sync.Map //接收传感器push来的数据,解析并上传到云端 func push(c *gin.Context) { - nowtime := time.Now() + data := c.PostForm("d") - data := c.PostForm("d") + go dealData(data) + + log.Println("data:", data) + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": data}) + +} + +func dealData(data string) string{ + + nowtime := time.Now() log.Println("yunhorndeug.push.data|", data) - go pushCODE1007(data) +// go pushCODE1007(data) alldata := strings.Split(data, "#") if len(alldata) != 2 { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"}) + return "" } else { valuedata := strings.Split(alldata[1], "*") if len(valuedata) < 1 { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"}) + return "" } dtype, error := strconv.Atoi(valuedata[0]) if error != nil { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errtype"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errtype"}) + return "" } var nowTmpData = "1#0" if dtype == 1 { if len(valuedata) != 3 { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "valuedata not 3"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "valuedata not 3"}) + return "" } addr, error := strconv.Atoi(alldata[0]) if error != nil { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "erraddr"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "erraddr"}) + return "" } cs2001, error := strconv.Atoi(valuedata[1]) if error != nil { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errcs2001"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errcs2001"}) + return "" } tof, error := strconv.Atoi(valuedata[2]) if error != nil { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errtof"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errtof"}) + return "" + } + + if tof ==0{ + log.Println("tof is zero") + return "" } if addr == 1 { @@ -195,13 +218,13 @@ func push(c *gin.Context) { if nowTmpData == "1#0" { if durationAsInt64 < extensionOutTime { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return "" } } else { if durationAsInt64 < extensionInTime { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return "" } } maledemoDevice.DATA["data1"] = 0 @@ -250,13 +273,13 @@ func push(c *gin.Context) { if nowTmpData == "1#0" { if durationAsInt64 < extensionOutTime { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return "" } } else { if durationAsInt64 < extensionInTime { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return "" } } maledemoDevice.DATA["data2"] = 0 @@ -274,18 +297,18 @@ func push(c *gin.Context) { } else if dtype == 2 { //吸顶传感器 没有距离数据 if len(valuedata) != 2 { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "valuedata not 2,type2"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "valuedata not 2,type2"}) + return "" } addr, error := strconv.Atoi(alldata[0]) if error != nil { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "erraddr"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "erraddr"}) + return "" } cs2001, error := strconv.Atoi(valuedata[1]) if error != nil { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errcs2001"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errcs2001"}) + return "" } if cs2001 == 1 { @@ -324,13 +347,13 @@ func push(c *gin.Context) { if nowTmpData == "1#0" { if durationAsInt64 < extensionOutTime { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return "" } } else { if durationAsInt64 < extensionInTime { - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) - return + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return "" } } @@ -344,11 +367,296 @@ func push(c *gin.Context) { } } } - } + return "" +} + +func pushv2(c *gin.Context){ + data := c.PostForm("d") + + go dealDatav2(data) log.Println("data:", data) - c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": data}) + c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "code": 1}) + +}z + +func dealDatav2(data string) string{ + + nowtime := time.Now() + + log.Println("yunhorndeug.push.data|", data) + + strs := []byte(data) + + addr := string(strs[:3]) + + var readyData bytes.Buffer + //地址 + readyData.WriteString(addr) + readyData.WriteString("#") + //类型 + readyData.WriteString(string(strs[3:4])) + readyData.WriteString("*") + //红外人体感应 + readyData.WriteString(string(strs[4:5])) + + newdtype,err :=strconv.Atoi(string(strs[3:4])) + if err!=nil{ + log.Println("type parse err",err) + return "" + } + + if newdtype==1{ + readyData.WriteString("*") + readyData.WriteString(string(strs[5:6])) + } + + + for i,v := range strs{ + log.Println("strs,i,v",i,v-48) + } + + log.Println("readyData:",readyData.String()) + +// go pushCODE1007(data) + + alldata := strings.Split(readyData.String(), "#") + + if len(alldata) != 2 { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"}) + return "" + } else { + + valuedata := strings.Split(alldata[1], "*") + + if len(valuedata) < 1 { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"}) + return "" + } + + dtype, error := strconv.Atoi(valuedata[0]) + if error != nil { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errtype"}) + return "" + } + + var nowTmpData = "1#0" + + if dtype == 1 { + if len(valuedata) != 3 { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "valuedata not 3"}) + return "" + } + addr, error := strconv.Atoi(alldata[0]) + if error != nil { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "erraddr"}) + return "" + } + cs2001, error := strconv.Atoi(valuedata[1]) + if error != nil { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errcs2001"}) + return "" + } + + tof, error := strconv.Atoi(valuedata[2]) + if error != nil { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errtof"}) + return "" + } + + if tof ==0{ + log.Println("tof is zero") + return "" + } + + if addr == 1 { + + if cs2001 == 1 || tof ==1 { + nowTmpData = "1#1" + } + + if oldData1 != nowTmpData { + dataMap.Store(addr, nowtime) + if oldData1 == "" { + //为空 直接改变状态 + maledemoDevice.DATA["data1"] = 0 + if nowTmpData == "1#1" { + maledemoDevice.DATA["data1"] = 1 + } + changeData(2, maledemoDevice) + } + //存储状态 + oldData1 = nowTmpData + + } else { + oldDevDataTime, ok := dataMap.Load(addr) + if !ok { + log.Println("load time err", ok) + } + + if ok { + if oldDevDataTime != nil { + //log.Println("t2.Sub(t1)", nowtime.Sub(oldDevDataTime.(time.Time))) + + var duration = nowtime.Sub(oldDevDataTime.(time.Time)).Seconds() + var durationAsInt64 = int(duration) + + log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData1, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64) + + if nowTmpData == "1#0" { + if durationAsInt64 < extensionOutTime { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return "" + } + } else { + if durationAsInt64 < extensionInTime { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return "" + } + } + maledemoDevice.DATA["data1"] = 0 + if nowTmpData == "1#1" { + maledemoDevice.DATA["data1"] = 1 + } + + changeData(2, maledemoDevice) + dataMap.Delete(addr) + } + } + } + + } else if addr == 2 { + if cs2001 == 1 || tof == 1 { + nowTmpData = "1#1" + } + + if oldData2 != nowTmpData { + dataMap.Store(addr, nowtime) + if oldData2 == "" { + //为空 直接改变状态 + maledemoDevice.DATA["data2"] = 0 + if nowTmpData == "1#1" { + maledemoDevice.DATA["data2"] = 1 + } + changeData(2, maledemoDevice) + } + //存储状态 + oldData2 = nowTmpData + + } else { + oldDevDataTime, ok := dataMap.Load(addr) + if !ok { + log.Println("load time err", ok) + } + + if ok { + if oldDevDataTime != nil { + //log.Println("t2.Sub(t1)", nowtime.Sub(oldDevDataTime.(time.Time))) + + var duration = nowtime.Sub(oldDevDataTime.(time.Time)).Seconds() + var durationAsInt64 = int(duration) + + log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData2, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64) + + if nowTmpData == "1#0" { + if durationAsInt64 < extensionOutTime { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return "" + } + } else { + if durationAsInt64 < extensionInTime { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return "" + } + } + maledemoDevice.DATA["data2"] = 0 + if nowTmpData == "1#1" { + maledemoDevice.DATA["data2"] = 1 + } + + changeData(2, maledemoDevice) + dataMap.Delete(addr) + } + } + } + } + + } else if dtype == 2 { + //吸顶传感器 没有距离数据 + if len(valuedata) != 2 { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "valuedata not 2,type2"}) + return "" + } + addr, error := strconv.Atoi(alldata[0]) + if error != nil { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "erraddr"}) + return "" + } + cs2001, error := strconv.Atoi(valuedata[1]) + if error != nil { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errcs2001"}) + return "" + } + + if cs2001 == 1 { + nowTmpData = "1#1" + } + + if oldData3 != nowTmpData { + dataMap.Store(addr, nowtime) + if oldData3 == "" { + //为空 直接改变状态 + femaledemoDevice.DATA["data1"] = 0 + if nowTmpData == "1#1" { + femaledemoDevice.DATA["data1"] = 1 + } + changeData(2, maledemoDevice) + } + //存储状态 + oldData3 = nowTmpData + + } else { + oldDevDataTime, ok := dataMap.Load(addr) + if !ok { + log.Println("load time err", ok) + } + + if ok { + if oldDevDataTime != nil { + //log.Println("t2.Sub(t1)", nowtime.Sub(oldDevDataTime.(time.Time))) + + var duration = nowtime.Sub(oldDevDataTime.(time.Time)).Seconds() + var durationAsInt64 = int(duration) + + var tof = 0 + + log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData3, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64) + + if nowTmpData == "1#0" { + if durationAsInt64 < extensionOutTime { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return "" + } + } else { + if durationAsInt64 < extensionInTime { + // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) + return "" + } + } + + femaledemoDevice.DATA["data1"] = 0 + if nowTmpData == "1#1" { + femaledemoDevice.DATA["data1"] = 1 + } + changeData(3, femaledemoDevice) + dataMap.Delete(addr) + } + } + } + } + } + return "" } //发送code1007数据到云端 diff --git a/tcpserver.go b/tcpserver.go index f99eca0..2593653 100644 --- a/tcpserver.go +++ b/tcpserver.go @@ -9,11 +9,14 @@ import ( //"strings" "time" // "go-study/socket/config" + "bytes" + "strconv" + ) func handleConn(conn net.Conn) { - log.Println("begin handleConn,cliendAddr:", conn.RemoteAddr()) + log.Println("yunhorndeug.push.data.tcp.begin handleConn,cliendAddr:", conn.RemoteAddr()) defer conn.Close() @@ -61,50 +64,146 @@ func handleConn(conn net.Conn) { } } } + func readConn(conn net.Conn, readChan chan<- []byte, stopChan chan<- bool) { - data_buf := make(chan []byte) - Rdata := make([]byte, 0) + + // data_buf := make(chan []byte) + + // Rdata := make([]byte, 0) data := make([]byte, 256) + Rdata2 := make([]byte, 0) - go func() { - for { - select { - case kkdata := <-data_buf: //如果有数据,下面打印。但是有可能ch一直没数据 - Rdata = append(Rdata, kkdata...) - //log.Println("kkdata:",kkdata) - case <-time.After(50 * time.Millisecond): //上面的ch如果一直没数据会阻塞,那么select也会检测其他case条件,检测到后3秒超时 - // log.Println("超时") - if len(Rdata) > 4 { - readChan <- Rdata - Rdata = make([]byte, 0) - } - //strData := string(Rdata) - //Rdata = make([]byte,0) - //log.Println("Received:", strData) - - //readChan <- Rdata - //Rdata = make([]byte,0) - } - } - }() + // go func() { + // for { + // select { + // case kkdata := <-data_buf: //如果有数据,下面打印。但是有可能ch一直没数据 + // // log.Println("yunhorndeug.push.data.tcp|",kkdata) + // + // log.Println("###########################yunhorndeug.push.data.tcp.kkdata:",kkdata) + // Rdata = append(Rdata, kkdata...) + // Rdata2 = append(Rdata2,Rdata...) + // count := 0 + // for _,v := range Rdata{ + // if v==0{ + // break; + // } + // count++ + // } + // + // Rdata2 = make([]byte, count) + // for i,v := range Rdata{ + // if v==0{ + // break; + // } + // Rdata2[i]=v + // } + // + // + // log.Println("---------------------------yunhorndeug.push.data.tcp.Rdata:",Rdata2) + // Rdata2 = make([]byte, 0) + // //log.Println("kkdata:",kkdata) + // case <-time.After(50 * time.Millisecond): //上面的ch如果一直没数据会阻塞,那么select也会检测其他case条件,检测到后3秒超时 + // // log.Println("超时") + // if len(Rdata) > 4 { + // readChan <- Rdata + // Rdata = make([]byte, 0) + // } + // //strData := string(Rdata) + // //Rdata = make([]byte,0) + // //log.Println("Received:", strData) + // + // //readChan <- Rdata + // //Rdata = make([]byte,0) + // } + // } + // }() for { // data := make([]byte, config.SERVER_RECV_LEN) //data2 := make([]byte,256) - _, err := conn.Read(data) + reqLen, err := conn.Read(data) if err != nil { log.Println(err) break } - // log.Println(DEVICEDATAS) - log.Println("read.data:%d,%s", Bytes2Bits(data[3:4])[0],conn.RemoteAddr()) - data_buf <- data + buffer := new(bytes.Buffer) + continueCount := 0 + log.Println("yunhorndeug.push.data.tcp.reqLen",reqLen) + for i, b := range data[:reqLen] { + + if continueCount>0{ + continueCount-- + continue; + } + + s := strconv.FormatInt(int64(b&0xff), 16) + if len(s) == 1 { + buffer.WriteString("0") + } + buffer.WriteString(s) + + // log.Println(b) + //分隔符 + end :=0 + if b==254 && i>3{ + addrs := data[i-4:i] + //尿布台数据,地址1位 数据2位 + dataType := data[i+1] + values := make([]byte,0) + if data[i+1] == 1 { + continueCount = 3 + end = 4 + //类型为1 数据量为2 + values = data[i+2:i+4] + }else if dataType == 2{ + //类型为2 数据量位1 + values = data[i+2:i+3] + continueCount = 2 + end = 3 + } + log.Println("yunhorndeug.push.data.tcp.addr",addrs) + log.Println("yunhorndeug.push.data.tcp.type",dataType) + log.Println("yunhorndeug.push.data.tcp.values",values) + // var buffer bytes.Buffer + // buffer.Write(addrs) + // buffer.Write(dataType) + // buffer.Write(values) + + // go dealDatav3(data[i-4:i+end]) + + } + } + + + + // 转化为字符串 + log.Println("yunhorndeug.push.data.tcp.16data:",buffer.String()) + + Rdata2 = make([]byte, reqLen) + for i,v := range data[:reqLen]{ + Rdata2[i]=v + } + + log.Println("===========================yunhorndeug.push.data.tcp.origin.Rdata:",Rdata2) + + // Rdata2 = make([]byte, count) + + // log.Println("read.data:%d,%s", Bytes2Bits(data[3:4])[0],conn.RemoteAddr()) + + // data_buf <- data + + data = make([]byte, 256) } stopChan <- true } +//BytesCombine 多个[]byte数组合并成一个[]byte +func BytesCombine(pBytes ...[]byte) []byte { + return bytes.Join(pBytes, []byte("")) +} + func writeConn(conn net.Conn, writeChan <-chan string, stopChan chan<- bool) { for { strData := <-writeChan From cca97cc6945ffd6e0d75c7a635d9a9d20b2c94b8 Mon Sep 17 00:00:00 2001 From: fish Date: Fri, 26 Apr 2019 17:02:00 +0800 Subject: [PATCH 07/15] =?UTF-8?q?=E5=AE=8C=E5=96=84tcp=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=8E=A5=E6=94=B6=E4=BB=A5=E5=8F=8A=E6=9B=B4=E6=96=B0=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/gateway.conf | 60 +++++-- loadconfig.go | 22 +++ router.go | 401 +++++++++++++++++----------------------------- tcpserver.go | 23 +-- 4 files changed, 233 insertions(+), 273 deletions(-) diff --git a/conf/gateway.conf b/conf/gateway.conf index c2573a1..7c0f7fc 100644 --- a/conf/gateway.conf +++ b/conf/gateway.conf @@ -5,19 +5,15 @@ "location": [113.960347, 22.54143], "单位": "深圳市云兴科技", "config": [ - { - "id": "8E146028-E1B1-4AC9-8F47-01376A22CB35", - "version": "yunhorn_kgl_c8_v1", - "data": [ - ["女厕位", 1] - ] - }, { "id": "7BB22E6A-ED0D-4161-8370-6B722D3683B7", - "version": "yunhorn_kgl_c8_v1", + "version": "yunhorn_kgl_c16_v1", "data": [ ["男厕位", 1], - ["男厕位", 2] + ["男厕位", 2], + ["女厕位", 1], + ["女厕位", 2], + ["男厕位", 5] ] } ] @@ -48,11 +44,53 @@ "id":"018B5704-55BE-40CA-9D3E-90EF157C2489" } ], + "lora_nodes":[ + { + "adr":"0c521618", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data1", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" + }, + { + "adr":"0c3b4f14", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data2", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" + }, + { + "adr":"0c451d14", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data3", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" + }, + { + "adr":"0c471714", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data4", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" + }, + { + "adr":"0c093e17", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data5", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" + } + ], "devices_list": [ ["4E5D52DD-EB81-43C0-A2B6-04E432412EBA", "loraport", "yunhorn_kgl_l_v1", "1"], ["deb03e28-ddcb-4e5d-aa31-d870a1f0f09b", "loraport", "yunhorn_kgl_c8_v1", "1"], - ["7BB22E6A-ED0D-4161-8370-6B722D3683B7", "loraport", "yunhorn_kgl_c8_v1", "2"], - ["8E146028-E1B1-4AC9-8F47-01376A22CB35", "loraport", "yunhorn_kgl_c8_v1", "3"] + ["7BB22E6A-ED0D-4161-8370-6B722D3683B7", "loraport", "yunhorn_kgl_c16_v1", "1"], + ["8E146028-E1B1-4AC9-8F47-01376A22CB35", "loraport", "yunhorn_kgl_c8_v1", "2"] ], "serialports_list": { "loraport": { diff --git a/loadconfig.go b/loadconfig.go index e93df7f..43a28e5 100644 --- a/loadconfig.go +++ b/loadconfig.go @@ -8,6 +8,7 @@ import ( "os" "strconv" "time" + "sync" ) type Traffic struct { @@ -29,6 +30,7 @@ type Conf struct { DEBUG bool `json:"debug"` OPENSERIAL bool `json:"openserial"` WIRELESSSLAVEDEVICES []WirelessSlaveDevice `json:"wireless_slave_devices"` + LORANODES []LoraNode `json:"lora_nodes"` } //无线 下位机 @@ -71,6 +73,17 @@ type Serialconf struct { NOTE string `json:"note"` } +type LoraNode struct{ + ADR string `json:"adr"` + LOCATION_TYPE string `json:"location_type"` + LOCATION_CODE string `json:"location_code"` + LOCATION_DATA string `json:"location_data"` + TIME time.Time `json:"time"` + CURRENT_DATA int `json:"current_data"` + CHECK_TIME bool `json:"check_time"` + DEVICE string `json:"device"` +} + var conf Conf var DEVICEDATAS Devicedatas var demoDevice Device @@ -80,6 +93,8 @@ var maledemoDevice Device var db, _ = sql.Open("sqlite3", "./db/gateway.db") +var loraNodeMap sync.Map + // 加载配置文件 func init() { @@ -99,6 +114,13 @@ func init() { // log.Println(i.ID) // } + for _,v := range conf.LORANODES { + v.CURRENT_DATA = -1 + // log.Println("&&&&&&&&&&&&&&&&&&&",v) + v.TIME = time.Now() + loraNodeMap.Store(v.ADR,v) + } + DEVICEDATAS.Lock() DEVICEDATAS.DATA = make(map[string]Device) //初始化设备,目前conf.DEVICES_LIST diff --git a/router.go b/router.go index cfe6e3e..09bfb9e 100644 --- a/router.go +++ b/router.go @@ -371,291 +371,175 @@ func dealData(data string) string{ return "" } + func pushv2(c *gin.Context){ data := c.PostForm("d") - go dealDatav2(data) + // go dealDatav2(data) log.Println("data:", data) c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "code": 1}) -}z +} -func dealDatav2(data string) string{ +func dealDatav3(data []byte) string{ nowtime := time.Now() log.Println("yunhorndeug.push.data|", data) - strs := []byte(data) + strs := data - addr := string(strs[:3]) + buffer := new(bytes.Buffer) + for _, b := range data[:4] { + s := strconv.FormatInt(int64(b&0xff), 16) + if len(s) == 1 { + buffer.WriteString("0") + } + buffer.WriteString(s) + } + + adr := buffer.String() var readyData bytes.Buffer + + datatype := data[5] + + cs2001 := data[6] + + datatypeStr := strconv.FormatInt(int64(data[5]&0xff), 16) + + cs2001Str := strconv.FormatInt(int64(data[6]&0xff), 16) + //地址 - readyData.WriteString(addr) + readyData.WriteString(buffer.String()) readyData.WriteString("#") //类型 - readyData.WriteString(string(strs[3:4])) + readyData.WriteString(datatypeStr) readyData.WriteString("*") //红外人体感应 - readyData.WriteString(string(strs[4:5])) + readyData.WriteString(cs2001Str) - newdtype,err :=strconv.Atoi(string(strs[3:4])) - if err!=nil{ - log.Println("type parse err",err) - return "" - } + newdtype := strs[5] + + tmp := []byte{0, 0} + tof := tmp[0] if newdtype==1{ + tof = data[7] + tofTmp := strconv.FormatInt(int64(data[7]&0xff), 10) readyData.WriteString("*") - readyData.WriteString(string(strs[5:6])) + readyData.WriteString(tofTmp) } - - for i,v := range strs{ - log.Println("strs,i,v",i,v-48) - } - - log.Println("readyData:",readyData.String()) + // log.Println("readyData:",readyData.String()) // go pushCODE1007(data) - alldata := strings.Split(readyData.String(), "#") + //默认当前无人占用 + current := 0 - if len(alldata) != 2 { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"}) - return "" - } else { - - valuedata := strings.Split(alldata[1], "*") - - if len(valuedata) < 1 { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"}) - return "" + if datatype == 1 { + //尿布台类型 + if cs2001==1 || tof<130{ + //有人占用 + current = 1 } - - dtype, error := strconv.Atoi(valuedata[0]) - if error != nil { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errtype"}) - return "" - } - - var nowTmpData = "1#0" - - if dtype == 1 { - if len(valuedata) != 3 { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "valuedata not 3"}) - return "" - } - addr, error := strconv.Atoi(alldata[0]) - if error != nil { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "erraddr"}) - return "" - } - cs2001, error := strconv.Atoi(valuedata[1]) - if error != nil { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errcs2001"}) - return "" - } - - tof, error := strconv.Atoi(valuedata[2]) - if error != nil { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errtof"}) - return "" - } - - if tof ==0{ - log.Println("tof is zero") - return "" - } - - if addr == 1 { - - if cs2001 == 1 || tof ==1 { - nowTmpData = "1#1" - } - - if oldData1 != nowTmpData { - dataMap.Store(addr, nowtime) - if oldData1 == "" { - //为空 直接改变状态 - maledemoDevice.DATA["data1"] = 0 - if nowTmpData == "1#1" { - maledemoDevice.DATA["data1"] = 1 - } - changeData(2, maledemoDevice) - } - //存储状态 - oldData1 = nowTmpData - - } else { - oldDevDataTime, ok := dataMap.Load(addr) - if !ok { - log.Println("load time err", ok) - } - - if ok { - if oldDevDataTime != nil { - //log.Println("t2.Sub(t1)", nowtime.Sub(oldDevDataTime.(time.Time))) - - var duration = nowtime.Sub(oldDevDataTime.(time.Time)).Seconds() - var durationAsInt64 = int(duration) - - log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData1, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64) - - if nowTmpData == "1#0" { - if durationAsInt64 < extensionOutTime { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) - return "" - } - } else { - if durationAsInt64 < extensionInTime { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) - return "" - } - } - maledemoDevice.DATA["data1"] = 0 - if nowTmpData == "1#1" { - maledemoDevice.DATA["data1"] = 1 - } - - changeData(2, maledemoDevice) - dataMap.Delete(addr) - } - } - } - - } else if addr == 2 { - if cs2001 == 1 || tof == 1 { - nowTmpData = "1#1" - } - - if oldData2 != nowTmpData { - dataMap.Store(addr, nowtime) - if oldData2 == "" { - //为空 直接改变状态 - maledemoDevice.DATA["data2"] = 0 - if nowTmpData == "1#1" { - maledemoDevice.DATA["data2"] = 1 - } - changeData(2, maledemoDevice) - } - //存储状态 - oldData2 = nowTmpData - - } else { - oldDevDataTime, ok := dataMap.Load(addr) - if !ok { - log.Println("load time err", ok) - } - - if ok { - if oldDevDataTime != nil { - //log.Println("t2.Sub(t1)", nowtime.Sub(oldDevDataTime.(time.Time))) - - var duration = nowtime.Sub(oldDevDataTime.(time.Time)).Seconds() - var durationAsInt64 = int(duration) - - log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData2, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64) - - if nowTmpData == "1#0" { - if durationAsInt64 < extensionOutTime { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) - return "" - } - } else { - if durationAsInt64 < extensionInTime { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) - return "" - } - } - maledemoDevice.DATA["data2"] = 0 - if nowTmpData == "1#1" { - maledemoDevice.DATA["data2"] = 1 - } - - changeData(2, maledemoDevice) - dataMap.Delete(addr) - } - } - } - } - - } else if dtype == 2 { - //吸顶传感器 没有距离数据 - if len(valuedata) != 2 { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "valuedata not 2,type2"}) - return "" - } - addr, error := strconv.Atoi(alldata[0]) - if error != nil { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "erraddr"}) - return "" - } - cs2001, error := strconv.Atoi(valuedata[1]) - if error != nil { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errcs2001"}) - return "" - } - - if cs2001 == 1 { - nowTmpData = "1#1" - } - - if oldData3 != nowTmpData { - dataMap.Store(addr, nowtime) - if oldData3 == "" { - //为空 直接改变状态 - femaledemoDevice.DATA["data1"] = 0 - if nowTmpData == "1#1" { - femaledemoDevice.DATA["data1"] = 1 - } - changeData(2, maledemoDevice) - } - //存储状态 - oldData3 = nowTmpData - - } else { - oldDevDataTime, ok := dataMap.Load(addr) - if !ok { - log.Println("load time err", ok) - } - - if ok { - if oldDevDataTime != nil { - //log.Println("t2.Sub(t1)", nowtime.Sub(oldDevDataTime.(time.Time))) - - var duration = nowtime.Sub(oldDevDataTime.(time.Time)).Seconds() - var durationAsInt64 = int(duration) - - var tof = 0 - - log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData3, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64) - - if nowTmpData == "1#0" { - if durationAsInt64 < extensionOutTime { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) - return "" - } - } else { - if durationAsInt64 < extensionInTime { - // c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"}) - return "" - } - } - - femaledemoDevice.DATA["data1"] = 0 - if nowTmpData == "1#1" { - femaledemoDevice.DATA["data1"] = 1 - } - changeData(3, femaledemoDevice) - dataMap.Delete(addr) - } - } - } + }else if datatype==2{ + //吸顶类型 + if cs2001 ==1 { + //有人占用 + current = 1 } } + + // log.Println("loraNodeMap:",loraNodeMap) + loraNode, ok := loraNodeMap.Load(adr) + if !ok { + log.Println("load loraNode success ", ok) + return "" + } + // log.Println("load loraNode:",loraNode) + + log.Println("yunhorndeug.push.data.cuurent_data,current",loraNode.(LoraNode).CURRENT_DATA,current) + if loraNode.(LoraNode).CURRENT_DATA != current{ + //不相同,直接改变状态,更新时间 + + // loraNode.(LoraNode).CURRENT_DATA = current + // loraNode.(LoraNode).TIME = time.Now() + // loraNode.(LoraNode).CHECK_TIME = true + + newLoraNode := LoraNode{} + newLoraNode.CURRENT_DATA = current + newLoraNode.TIME = time.Now() + newLoraNode.CHECK_TIME=true + + newLoraNode.LOCATION_TYPE = loraNode.(LoraNode).LOCATION_TYPE + newLoraNode.LOCATION_CODE = loraNode.(LoraNode).LOCATION_CODE + newLoraNode.LOCATION_DATA = loraNode.(LoraNode).LOCATION_DATA + newLoraNode.DEVICE = loraNode.(LoraNode).DEVICE + + loraNodeMap.Store(adr,newLoraNode) + + //初次启动 + if loraNode.(LoraNode).CURRENT_DATA == -1{ + changeDataV2(newLoraNode) + } + + + }else{ + // 非首次 + if loraNode.(LoraNode).CHECK_TIME { + + var duration = nowtime.Sub(loraNode.(LoraNode).TIME).Seconds() + var durationAsInt64 = int(duration) + + log.Println("yunhorndeug.push.data.durationAsInt64:",durationAsInt64) + if current == 0 { + if durationAsInt64 < extensionOutTime { + return "" + } + }else{ + if durationAsInt64 < extensionInTime { + return "" + } + } + + //改变状态 + // loraNode.(LoraNode).CHECK_TIME = false + + newLoraNode := LoraNode{} + newLoraNode.CURRENT_DATA = current + newLoraNode.TIME = loraNode.(LoraNode).TIME + newLoraNode.CHECK_TIME= false + + newLoraNode.LOCATION_TYPE = loraNode.(LoraNode).LOCATION_TYPE + newLoraNode.LOCATION_CODE = loraNode.(LoraNode).LOCATION_CODE + newLoraNode.LOCATION_DATA = loraNode.(LoraNode).LOCATION_DATA + newLoraNode.DEVICE = loraNode.(LoraNode).DEVICE + loraNodeMap.Store(adr,newLoraNode) + + changeDataV2(newLoraNode) + }else{ + // loraNode.(LoraNode).CHECK_TIME = true + newLoraNode := LoraNode{} + newLoraNode.CURRENT_DATA = loraNode.(LoraNode).CURRENT_DATA + newLoraNode.TIME = time.Now() + newLoraNode.CHECK_TIME= true + + newLoraNode.LOCATION_TYPE = loraNode.(LoraNode).LOCATION_TYPE + newLoraNode.LOCATION_CODE = loraNode.(LoraNode).LOCATION_CODE + newLoraNode.LOCATION_DATA = loraNode.(LoraNode).LOCATION_DATA + newLoraNode.DEVICE = loraNode.(LoraNode).DEVICE + + loraNodeMap.Store(adr,newLoraNode) + } + } + + // log.Println("current:",current) + // log.Println("loraNode:",loraNode) + // log.Println("loraNode.time.is nil",(loraNode==nil)) + return "" } @@ -680,6 +564,17 @@ func changeData(num int, device Device) { DEVICEDATAS.DATA[demoDevice.VERSION+"_"+strconv.Itoa(num)] = device } +func changeDataV2(loraNode LoraNode){ + // log.Println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@") + // log.Println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@00000:",loraNode) + // log.Println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@11111:",DEVICEDATAS.DATA[loraNode.DEVICE]) + DEVICEDATAS.RLock() + DEVICEDATAS.DATA[loraNode.DEVICE].DATA[loraNode.LOCATION_DATA] = loraNode.CURRENT_DATA + DEVICEDATAS.RUnlock() + log.Println("yunhorndeug.push.data.@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@22222:",DEVICEDATAS.DATA[loraNode.DEVICE]) + // log.Println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@") +} + type EventNotificationAlert struct { IPADDRESS string `xml:"ipAddress" json:"ipAddress"` PROTOCOLTYPE string `xml:"protocolType" json:"protocolType"` @@ -873,9 +768,9 @@ func seat_api(c *gin.Context) { // log.Println("data:", DEVICEDATAS.DATA[version+"_"+num].DATA) //} - log.Println("============================devicedatas.data:", DEVICEDATAS.DATA[version+"_"+num].DATA) + // log.Println("============================devicedatas.data:", DEVICEDATAS.DATA[version+"_"+num].DATA) if DEVICEDATAS.DATA[version+"_"+num].DATA["data"+strconv.Itoa(k+1)] != nil { - log.Println("==========================do.data:", DEVICEDATAS.DATA[version+"_"+num].DATA["data"+strconv.Itoa(k+1)]) + // log.Println("==========================do.data:", DEVICEDATAS.DATA[version+"_"+num].DATA["data"+strconv.Itoa(k+1)]) j = append(j, DEVICEDATAS.DATA[version+"_"+num].DATA["data"+strconv.Itoa(k+1)]) } } diff --git a/tcpserver.go b/tcpserver.go index 2593653..e0d4e45 100644 --- a/tcpserver.go +++ b/tcpserver.go @@ -129,9 +129,13 @@ func readConn(conn net.Conn, readChan chan<- []byte, stopChan chan<- bool) { buffer := new(bytes.Buffer) continueCount := 0 - log.Println("yunhorndeug.push.data.tcp.reqLen",reqLen) + // log.Println("yunhorndeug.push.data.tcp.reqLen",reqLen) for i, b := range data[:reqLen] { + if reqLen<7{ + break + } + if continueCount>0{ continueCount-- continue; @@ -162,23 +166,24 @@ func readConn(conn net.Conn, readChan chan<- []byte, stopChan chan<- bool) { continueCount = 2 end = 3 } - log.Println("yunhorndeug.push.data.tcp.addr",addrs) - log.Println("yunhorndeug.push.data.tcp.type",dataType) - log.Println("yunhorndeug.push.data.tcp.values",values) + + log.Println("yunhorndeug.push.data.tcp:",buffer.String(),addrs,dataType,values) + // log.Println("yunhorndeug.push.data.tcp.addr",addrs) + // log.Println("yunhorndeug.push.data.tcp.type",dataType) + // log.Println("yunhorndeug.push.data.tcp.values",values) + // var buffer bytes.Buffer // buffer.Write(addrs) // buffer.Write(dataType) // buffer.Write(values) - // go dealDatav3(data[i-4:i+end]) - + go dealDatav3(data[i-4:i+end]) + } } - - // 转化为字符串 - log.Println("yunhorndeug.push.data.tcp.16data:",buffer.String()) + // log.Println("yunhorndeug.push.data.tcp.16data:",buffer.String()) Rdata2 = make([]byte, reqLen) for i,v := range data[:reqLen]{ From da82f1a7655eeab91b92895de9f0042471fb3aad Mon Sep 17 00:00:00 2001 From: fish Date: Sat, 27 Apr 2019 15:17:17 +0800 Subject: [PATCH 08/15] =?UTF-8?q?=E5=90=B8=E9=A1=B6=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E4=BC=A0=E6=84=9F=E5=99=A8=E4=BD=BF=E7=94=A8=E7=89=B9=E5=AE=9A?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router.go | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/router.go b/router.go index 09bfb9e..be6d0bd 100644 --- a/router.go +++ b/router.go @@ -48,6 +48,8 @@ func gw_router() { type DparkConf struct { ExtensionInTime int `json:"in"` ExtensionOutTime int `json:"out"` + ExtensionInTime2 int `json:"in2"` + ExtensionOutTime2 int `json:"out2"` } var dparkConf DparkConf @@ -407,6 +409,16 @@ func dealDatav3(data []byte) string{ cs2001 := data[6] + var R_data P1004_6 + R_data.CODE = 1008 + R_data.ID = adr + //尿布台 + R_data.VERSION = "yunhorn_2_v1" + R_data.ONLINE = true + R_data.DATA = make(map[string]interface{}) + R_data.DATA["cs2001"]=cs2001 + + datatypeStr := strconv.FormatInt(int64(data[5]&0xff), 16) cs2001Str := strconv.FormatInt(int64(data[6]&0xff), 16) @@ -427,11 +439,17 @@ func dealDatav3(data []byte) string{ if newdtype==1{ tof = data[7] + R_data.VERSION = "yunhorn_1_v1" + R_data.DATA["tof"]=tof tofTmp := strconv.FormatInt(int64(data[7]&0xff), 10) readyData.WriteString("*") readyData.WriteString(tofTmp) } + data_bufTmp, _ := json.Marshal(R_data) + data_buf := string(data_bufTmp) + go post_to_server(data_buf) + // log.Println("readyData:",readyData.String()) // go pushCODE1007(data) @@ -496,13 +514,29 @@ func dealDatav3(data []byte) string{ log.Println("yunhorndeug.push.data.durationAsInt64:",durationAsInt64) if current == 0 { - if durationAsInt64 < extensionOutTime { + //类型2 吸顶 + if datatype==2{ + if durationAsInt64 < extensionOutTime2 { + return "" + } + }else{ + if durationAsInt64 < extensionOutTime { + return "" + } + } + + }else{ + //类型2 吸顶 + if datatype==2{ + if durationAsInt64 < extensionInTime2 { return "" } - }else{ + }else{ if durationAsInt64 < extensionInTime { return "" } + } + } //改变状态 From 52f2c1aecfd11e9798322683be49d7e2d6440f6d Mon Sep 17 00:00:00 2001 From: fish Date: Sat, 27 Apr 2019 15:20:37 +0800 Subject: [PATCH 09/15] fix --- router.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/router.go b/router.go index be6d0bd..cb4195e 100644 --- a/router.go +++ b/router.go @@ -107,6 +107,10 @@ var extensionInTime = 6 //数据防抖 离开时间 var extensionOutTime = 10 +var extensionInTime2 = 0 + +var extensionOutTime2 = 0 + var oldData1 = "" var oldData2 = "" From e713cc12d09344da9805176068dbab7061f2a614 Mon Sep 17 00:00:00 2001 From: fish Date: Sat, 27 Apr 2019 15:33:48 +0800 Subject: [PATCH 10/15] =?UTF-8?q?fix=20=E6=97=A5=E5=BF=97=E6=89=93?= =?UTF-8?q?=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tcpserver.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tcpserver.go b/tcpserver.go index e0d4e45..bcf9c7a 100644 --- a/tcpserver.go +++ b/tcpserver.go @@ -172,6 +172,8 @@ func readConn(conn net.Conn, readChan chan<- []byte, stopChan chan<- bool) { // log.Println("yunhorndeug.push.data.tcp.type",dataType) // log.Println("yunhorndeug.push.data.tcp.values",values) + buffer := new(bytes.Buffer) + // var buffer bytes.Buffer // buffer.Write(addrs) // buffer.Write(dataType) From 5d693d27f8f1067510566256039f1339395aa20c Mon Sep 17 00:00:00 2001 From: fish Date: Sat, 27 Apr 2019 15:34:24 +0800 Subject: [PATCH 11/15] =?UTF-8?q?fix=20=E6=97=A5=E5=BF=97=E6=89=93?= =?UTF-8?q?=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tcpserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcpserver.go b/tcpserver.go index bcf9c7a..0170c28 100644 --- a/tcpserver.go +++ b/tcpserver.go @@ -172,7 +172,7 @@ func readConn(conn net.Conn, readChan chan<- []byte, stopChan chan<- bool) { // log.Println("yunhorndeug.push.data.tcp.type",dataType) // log.Println("yunhorndeug.push.data.tcp.values",values) - buffer := new(bytes.Buffer) + buffer = new(bytes.Buffer) // var buffer bytes.Buffer // buffer.Write(addrs) From 61754365307019776ebc3df3370d93fe4786cff6 Mon Sep 17 00:00:00 2001 From: fish Date: Sat, 27 Apr 2019 15:50:14 +0800 Subject: [PATCH 12/15] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=BB=B6=E6=97=B6?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E9=85=8D=E7=BD=AE=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/router.go b/router.go index cb4195e..5608e20 100644 --- a/router.go +++ b/router.go @@ -520,11 +520,11 @@ func dealDatav3(data []byte) string{ if current == 0 { //类型2 吸顶 if datatype==2{ - if durationAsInt64 < extensionOutTime2 { + if durationAsInt64 < extensionOutTime2 || extensionOutTime2<=0 { return "" } }else{ - if durationAsInt64 < extensionOutTime { + if durationAsInt64 < extensionOutTime || extensionOutTime<=0 { return "" } } @@ -532,11 +532,11 @@ func dealDatav3(data []byte) string{ }else{ //类型2 吸顶 if datatype==2{ - if durationAsInt64 < extensionInTime2 { + if durationAsInt64 < extensionInTime2 || extensionOutTime2<=0 { return "" } }else{ - if durationAsInt64 < extensionInTime { + if durationAsInt64 < extensionInTime || extensionInTime<=0 { return "" } } From 3d781d12fa8eab15bc80850a526108431702955c Mon Sep 17 00:00:00 2001 From: fish Date: Sat, 27 Apr 2019 17:07:25 +0800 Subject: [PATCH 13/15] =?UTF-8?q?fix=20data=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tcpserver.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tcpserver.go b/tcpserver.go index 0170c28..6446643 100644 --- a/tcpserver.go +++ b/tcpserver.go @@ -130,6 +130,7 @@ func readConn(conn net.Conn, readChan chan<- []byte, stopChan chan<- bool) { buffer := new(bytes.Buffer) continueCount := 0 // log.Println("yunhorndeug.push.data.tcp.reqLen",reqLen) + // log.Println("$$$$$$$$$$$$$$$$$$$$$$$$$",data[:reqLen]) for i, b := range data[:reqLen] { if reqLen<7{ @@ -149,6 +150,8 @@ func readConn(conn net.Conn, readChan chan<- []byte, stopChan chan<- bool) { // log.Println(b) //分隔符 + // log.Println("$$$$$$$$$$$$$$$$$$$$$$$$$",i,reqLen) + // log.Println("$$$$$$$$$$$$$$$$$$$$$$$$$",data[reqLen]) end :=0 if b==254 && i>3{ addrs := data[i-4:i] @@ -156,15 +159,29 @@ func readConn(conn net.Conn, readChan chan<- []byte, stopChan chan<- bool) { dataType := data[i+1] values := make([]byte,0) if data[i+1] == 1 { + continueCount = 3 end = 4 + + if i+4>=reqLen{ + continue + } + //类型为1 数据量为2 values = data[i+2:i+4] + + + }else if dataType == 2{ //类型为2 数据量位1 - values = data[i+2:i+3] + continueCount = 2 end = 3 + + if i+3 >=reqLen{ + continue + } + values = data[i+2:i+3] } log.Println("yunhorndeug.push.data.tcp:",buffer.String(),addrs,dataType,values) From c867893ebb3daf10da17501cf2eb5171657b5b33 Mon Sep 17 00:00:00 2001 From: fish Date: Sat, 27 Apr 2019 17:36:52 +0800 Subject: [PATCH 14/15] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router.go | 8 ++++---- tcpserver.go | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/router.go b/router.go index 5608e20..a1a34f7 100644 --- a/router.go +++ b/router.go @@ -520,11 +520,11 @@ func dealDatav3(data []byte) string{ if current == 0 { //类型2 吸顶 if datatype==2{ - if durationAsInt64 < extensionOutTime2 || extensionOutTime2<=0 { + if durationAsInt64 < extensionOutTime2 && extensionOutTime2>0 { return "" } }else{ - if durationAsInt64 < extensionOutTime || extensionOutTime<=0 { + if durationAsInt64 < extensionOutTime && extensionOutTime>0 { return "" } } @@ -532,11 +532,11 @@ func dealDatav3(data []byte) string{ }else{ //类型2 吸顶 if datatype==2{ - if durationAsInt64 < extensionInTime2 || extensionOutTime2<=0 { + if durationAsInt64 < extensionInTime2 && extensionOutTime2>0 { return "" } }else{ - if durationAsInt64 < extensionInTime || extensionInTime<=0 { + if durationAsInt64 < extensionInTime && extensionInTime>0 { return "" } } diff --git a/tcpserver.go b/tcpserver.go index 6446643..dbb110f 100644 --- a/tcpserver.go +++ b/tcpserver.go @@ -163,22 +163,22 @@ func readConn(conn net.Conn, readChan chan<- []byte, stopChan chan<- bool) { continueCount = 3 end = 4 - if i+4>=reqLen{ + if i+4>reqLen{ + log.Println("yunhorndeug.push.data.tcp.fq",buffer.String(),addrs,dataType) continue } //类型为1 数据量为2 values = data[i+2:i+4] - - }else if dataType == 2{ //类型为2 数据量位1 continueCount = 2 end = 3 - if i+3 >=reqLen{ + if i+3 >reqLen{ + log.Println("yunhorndeug.push.data.tcp.fq",buffer.String(),addrs,dataType) continue } values = data[i+2:i+3] From fca9fbd350a25841be227d2d7a193f9255b4ac4c Mon Sep 17 00:00:00 2001 From: fish Date: Sun, 5 May 2019 10:38:57 +0800 Subject: [PATCH 15/15] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=98=B2=E6=8A=9615s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/gateway.conf | 83 +++++++++++++++++++++++++++++++++++++++++------ do_send_data.go | 1 + router.go | 20 ++++++++++-- tcpserver.go | 2 +- 4 files changed, 92 insertions(+), 14 deletions(-) diff --git a/conf/gateway.conf b/conf/gateway.conf index 7c0f7fc..89deb8b 100644 --- a/conf/gateway.conf +++ b/conf/gateway.conf @@ -13,7 +13,14 @@ ["男厕位", 2], ["女厕位", 1], ["女厕位", 2], - ["男厕位", 5] + ["男厕位", 3], + ["男厕位", 4], + ["男厕位", 5], + ["男厕位", 6], + ["男厕位", 7], + ["男厕位", 8], + ["女厕位", 3], + ["女厕位", 4] ] } ] @@ -49,18 +56,18 @@ "adr":"0c521618", "location_type":"changing_desk", "location_code":"spao", - "location_data":"data1", + "location_data":"data6", "current_data":0, "device":"yunhorn_kgl_c16_v1_1" }, { - "adr":"0c3b4f14", - "location_type":"changing_desk", - "location_code":"spao", - "location_data":"data2", - "current_data":0, - "device":"yunhorn_kgl_c16_v1_1" - }, + "adr":"0c473018", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data7", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" + }, { "adr":"0c451d14", "location_type":"changing_desk", @@ -84,7 +91,63 @@ "location_data":"data5", "current_data":0, "device":"yunhorn_kgl_c16_v1_1" - } + }, + { + "adr":"0c3e3c14", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data2", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" + }, + { + "adr":"0c3c1214", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data8", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" + }, + { + "adr":"0c3d3c14", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data10", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" + }, + { + "adr":"0c3b4f14", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data9", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" +}, +{ + "adr":"0c360514", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data1", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" +}, +{ + "adr":"123", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data11", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" +}, +{ + "adr":"0c0a2017", + "location_type":"changing_desk", + "location_code":"spao", + "location_data":"data12", + "current_data":0, + "device":"yunhorn_kgl_c16_v1_1" +} ], "devices_list": [ ["4E5D52DD-EB81-43C0-A2B6-04E432412EBA", "loraport", "yunhorn_kgl_l_v1", "1"], diff --git a/do_send_data.go b/do_send_data.go index 7d1e641..37d84de 100644 --- a/do_send_data.go +++ b/do_send_data.go @@ -20,6 +20,7 @@ type P1004_6 struct { VERSION string `json:"version"` ONLINE bool `json:"online"` DATA map[string]interface{} `json:"data"` + TIMESTAMP int64 `json:"timestamp"` } // 发送数据 diff --git a/router.go b/router.go index a1a34f7..c9ce9f6 100644 --- a/router.go +++ b/router.go @@ -105,7 +105,7 @@ var reactTof = 1650 var extensionInTime = 6 //数据防抖 离开时间 -var extensionOutTime = 10 +var extensionOutTime = 15 var extensionInTime2 = 0 @@ -449,6 +449,7 @@ func dealDatav3(data []byte) string{ readyData.WriteString("*") readyData.WriteString(tofTmp) } + R_data.TIMESTAMP=time.Now().Unix() data_bufTmp, _ := json.Marshal(R_data) data_buf := string(data_bufTmp) @@ -483,7 +484,7 @@ func dealDatav3(data []byte) string{ } // log.Println("load loraNode:",loraNode) - log.Println("yunhorndeug.push.data.cuurent_data,current",loraNode.(LoraNode).CURRENT_DATA,current) + //log.Println("yunhorndeug.push.data.cuurent_data,current",loraNode.(LoraNode).CURRENT_DATA,current) if loraNode.(LoraNode).CURRENT_DATA != current{ //不相同,直接改变状态,更新时间 @@ -508,6 +509,11 @@ func dealDatav3(data []byte) string{ changeDataV2(newLoraNode) } + if (datatype==2 && (extensionInTime2<=0 || extensionOutTime2<=0)){ + newLoraNode.CURRENT_DATA = current + changeDataV2(newLoraNode) + } + }else{ // 非首次 @@ -532,7 +538,7 @@ func dealDatav3(data []byte) string{ }else{ //类型2 吸顶 if datatype==2{ - if durationAsInt64 < extensionInTime2 && extensionOutTime2>0 { + if durationAsInt64 < extensionInTime2 && extensionInTime2>0 { return "" } }else{ @@ -560,6 +566,7 @@ func dealDatav3(data []byte) string{ changeDataV2(newLoraNode) }else{ // loraNode.(LoraNode).CHECK_TIME = true + newLoraNode := LoraNode{} newLoraNode.CURRENT_DATA = loraNode.(LoraNode).CURRENT_DATA newLoraNode.TIME = time.Now() @@ -570,7 +577,14 @@ func dealDatav3(data []byte) string{ newLoraNode.LOCATION_DATA = loraNode.(LoraNode).LOCATION_DATA newLoraNode.DEVICE = loraNode.(LoraNode).DEVICE + if (datatype==2 && (extensionInTime2<=0 || extensionOutTime2<=0)){ + newLoraNode.CURRENT_DATA = current + changeDataV2(newLoraNode) + } + loraNodeMap.Store(adr,newLoraNode) + + } } diff --git a/tcpserver.go b/tcpserver.go index dbb110f..b794b32 100644 --- a/tcpserver.go +++ b/tcpserver.go @@ -209,7 +209,7 @@ func readConn(conn net.Conn, readChan chan<- []byte, stopChan chan<- bool) { Rdata2[i]=v } - log.Println("===========================yunhorndeug.push.data.tcp.origin.Rdata:",Rdata2) + // log.Println("===========================yunhorndeug.push.data.tcp.origin.Rdata:",Rdata2) // Rdata2 = make([]byte, count)