├── .gitignore ├── README.md ├── beidou └── beidou.py ├── document ├── README.md ├── 作品说明书.docx ├── 创业计划书.docx ├── 基于物联网技术大气环境监测三维可视化的智能终端系统.zip └── 空气监测报警系统.pptx ├── machinelearning ├── data.dat ├── demo │ ├── demo1.py │ ├── demo2.py │ ├── foo.txt │ ├── regression.py │ └── workfile └── getAirElement.py ├── sensor ├── arduino │ ├── README.md │ ├── sensor │ │ └── sensor.ino │ └── sensor_old │ │ └── sensor_old.ino ├── hardware │ └── FWB.ms14 └── raspberrypi │ ├── GPIO.jpg │ ├── README.md │ ├── color.py │ ├── dashboard.py │ ├── sensor.py │ ├── sensor_api.py │ ├── sensor_api_old.py │ ├── sensor_backup.py │ ├── sensor_old.py │ ├── shell.py │ ├── test.py │ ├── test1.py │ ├── test_pygame.py │ ├── test_tkinter.py │ ├── wts11.ttf │ ├── yeelink_api.py │ ├── yeelink_config.py │ ├── 仪表盘.png │ ├── 仪表盘1.jpg │ ├── 仪表盘2.jpg │ └── 界面_0.png ├── server └── weixin │ ├── access_token.dat │ ├── can_scanf │ ├── index.php │ ├── index_bak.php │ ├── menu.php │ ├── output_sqlite.sql │ ├── sqlite │ ├── sqlitedb.db │ ├── sqlitedb_backup.db │ ├── sqlitedb_bak1.db │ ├── test.php │ ├── test2.php │ ├── test3.php │ ├── test4.php │ ├── test5.php │ └── warningtemplate.php └── sg90.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.xml 2 | *.pyc 3 | .idea/ 4 | *.ms14 (Security copy) 5 | .vs/ 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # air_monitor 2 | 3 | 4 | -------------------------------------------------------------------------------- /beidou/beidou.py: -------------------------------------------------------------------------------- 1 | import serial 2 | import time 3 | 4 | 5 | # import _thread 6 | # from XOR_CheckSum import XOR_CheckSum_string 7 | 8 | 9 | def XOR_CheckSum_string(m_str, encoding="utf-8"): 10 | if str == type(m_str): 11 | try: 12 | m_str = bytes(m_str, encoding=encoding) 13 | except: 14 | # m_str = bytes(m_str) 15 | m_str = m_str.encode(encoding=encoding) 16 | sum = 0x0 17 | # print(m_str) 18 | # print(type(m_str)) 19 | for c in m_str: 20 | try: 21 | sum = sum ^ c 22 | except: 23 | # print(c) 24 | sum = sum ^ ord(c) 25 | sum = sum ^ 0x0 26 | return sum 27 | 28 | 29 | def read_serial(serial, transfer_method=2, encoding="gb2312"): 30 | while True: 31 | line = serial.readline() 32 | print(line) 33 | 34 | if line[3:6] == b'TXR': 35 | tmp = line.split(b',')[-1] 36 | msg = tmp.split(b'*')[0] 37 | if transfer_method == '2' and msg[0:2] == b'A4': 38 | msg = msg[1:] 39 | try: 40 | # print("Receive message:",str(msg,encoding='utf-8')) 41 | print("Receive message:", msg.decode(encoding)) 42 | except: 43 | print("Receive message:", str(msg)) 44 | 45 | 46 | class TXA: 47 | def __init__(self, user_address, serial, sender_identifier='CC', communication_category='1', transfer_method='2', 48 | encoding="gb2312"): 49 | self.sender_identifier = sender_identifier 50 | self.user_address = user_address 51 | self.communication_category = communication_category 52 | self.transfer_method = transfer_method 53 | self.serial = serial 54 | self.encoding = encoding 55 | 56 | def message(self, content, address='', encoding=''): 57 | if address == '': 58 | address = self.user_address 59 | if encoding == '': 60 | encoding = self.encoding 61 | 62 | message_temp = self.sender_identifier + 'TXA' + ',' + \ 63 | address + ',' + \ 64 | self.communication_category + ',' + \ 65 | self.transfer_method + ',' 66 | message=bytes(message_temp,encoding) 67 | #if self.transfer_method=='2': 68 | # message=message+b'\xA4' 69 | message=message+bytes(content,encoding) 70 | #if self.transfer_method == 2: 71 | # message = 'A4' + message 72 | self.xor_checkSum = hex(XOR_CheckSum_string(message, encoding=encoding))[2:4] 73 | message = bytes('$',encoding) + message + bytes('*',encoding) + bytes(self.xor_checkSum,encoding) + bytes('\r\n',encoding) 74 | '''try: 75 | reslut = bytes(message, encoding=encoding) 76 | except: 77 | reslut = bytes(message)''' 78 | 79 | '''if self.transfer_method == 2:#''' 80 | # '''reslut = b'\xA4' + reslut''' 81 | 82 | #return reslut 83 | return message 84 | 85 | def send(self, message): 86 | self.serial.write(message) 87 | 88 | def read(self): 89 | try: 90 | import _thread 91 | _thread.start_new_thread(read_serial, (self.serial, self.transfer_method, self.encoding,)) 92 | except: 93 | import thread 94 | thread.start_new_thread(read_serial, (self.serial, self.transfer_method, self.encoding,)) 95 | 96 | 97 | def test(): 98 | ser = serial.Serial('/dev/ttyUSB1', 115200) 99 | print(ser) 100 | _thread.start_new_thread(read_serial, (ser,)) 101 | for i in range(5): 102 | # ser.write(b'$CCICA,0,00*7B\r\n') 103 | ser.write(b'$CCICI,0,00*73\r\n') 104 | # line = ser.readline() 105 | # print(line) 106 | time.sleep(1) 107 | 108 | for i in range(100): 109 | ser.write(b'$CCTXA,0247718,1,1,3132333435*70\r\n') 110 | time.sleep(80) 111 | 112 | ser.close() 113 | 114 | 115 | if __name__ == "__main__": 116 | '''print(hex(XOR_CheckSum_string('CCICA,0,00'))) 117 | print(hex(XOR_CheckSum_string('CCICI,0,00'))) 118 | print(hex(XOR_CheckSum_string('CCTXA,0247718,1,1,3132333435'))) 119 | 120 | print(hex(XOR_CheckSum_string(b'CCICA,0,00'))) 121 | print(hex(XOR_CheckSum_string(b'CCICI,0,00'))) 122 | print(hex(XOR_CheckSum_string(b'CCTXA,0247718,1,1,3132333435'))) 123 | 124 | print(hex(XOR_CheckSum_string(bytes('CCICA,0,00', encoding="utf-8")))) 125 | print(hex(XOR_CheckSum_string(bytes('CCICI,0,00', encoding="utf-8")))) 126 | print(hex(XOR_CheckSum_string(bytes('CCTXA,0247718,1,1,3132333435', encoding="utf-8"))))''' 127 | 128 | ser = serial.Serial('/dev/ttyUSB1', 115200) 129 | txa = TXA(user_address='0247718', serial=ser, transfer_method='2',encoding='gb2312') 130 | txa.read() 131 | 132 | '''test_msg=b'$CCTXA,0242407,1,2,A4B9E3D6DDBAA3C1C4BFC6BCBCD3D0CFDEB9ABCBBE*0F' 133 | print(test_msg) 134 | txa.send(message=test_msg) 135 | time.sleep(60)''' 136 | 137 | message = txa.message(content='3132333435') 138 | print(message) 139 | txa.send(message=message) 140 | time.sleep(60) 141 | 142 | message = txa.message(content='-3-132333435') 143 | print(message) 144 | txa.send(message=message) 145 | time.sleep(60) 146 | 147 | message = txa.message(content='-3--132333435') 148 | print(message) 149 | txa.send(message=message) 150 | time.sleep(60) 151 | 152 | message = txa.message(content='.3.132333435') 153 | print(message) 154 | txa.send(message=message) 155 | time.sleep(60) 156 | 157 | message = txa.message(content='.3..132333435') 158 | print(message) 159 | txa.send(message=message) 160 | time.sleep(60) 161 | 162 | message = txa.message(content='.-3.-13.2333435') 163 | print(message) 164 | txa.send(message=message) 165 | time.sleep(60) 166 | 167 | message = txa.message(content='.-3..--13.2333435') 168 | print(message) 169 | txa.send(message=message) 170 | time.sleep(60) 171 | 172 | message = txa.message(content='广州海聊科技..有限公--司12就3a给bc.-PM2.5-1.0CO-3.57') 173 | print(message) 174 | txa.send(message=message) 175 | time.sleep(60) 176 | 177 | # test() 178 | 8 179 | -------------------------------------------------------------------------------- /document/README.md: -------------------------------------------------------------------------------- 1 | 以后添加子树时,要选择实目录 2 | 即目录中有文件的,最好在提交一下,可以不推送 3 | 否则光是一个空目录,git是不认为那里有目录的,就会各种找不到文件,很麻烦 4 | -------------------------------------------------------------------------------- /document/作品说明书.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/document/作品说明书.docx -------------------------------------------------------------------------------- /document/创业计划书.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/document/创业计划书.docx -------------------------------------------------------------------------------- /document/基于物联网技术大气环境监测三维可视化的智能终端系统.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/document/基于物联网技术大气环境监测三维可视化的智能终端系统.zip -------------------------------------------------------------------------------- /document/空气监测报警系统.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/document/空气监测报警系统.pptx -------------------------------------------------------------------------------- /machinelearning/data.dat: -------------------------------------------------------------------------------- 1 | b'{"error":"You need to sign in or sign up before continuing."}' 2 | -------------------------------------------------------------------------------- /machinelearning/demo/demo1.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | 4 | def func(i, j): 5 | return 0.0015 * i - 0.99 * j + i / (i + j) 6 | 7 | 8 | num_node = 20 9 | with open('foo.txt', 'w') as f: 10 | for i in range(1, num_node): 11 | for j in range(1, num_node): 12 | ii = i * 1.0 / num_node 13 | jj = j * 1.0 / num_node 14 | print(ii, jj, func(ii, jj)) 15 | print(ii, jj, func(ii, jj), file=f) 16 | -------------------------------------------------------------------------------- /machinelearning/demo/demo2.py: -------------------------------------------------------------------------------- 1 | import regression 2 | from numpy import * 3 | import matplotlib.pyplot as plt 4 | 5 | 6 | def best_k(xArr, yArr): 7 | k_small = 0.01 8 | k_big = 2.0 9 | k = (k_big + k_small) / 2.0 10 | while True: 11 | yHat = regression.lwlrTest(xArr, xArr, yArr, k) 12 | yHat_small = regression.lwlrTest(xArr, xArr, yArr, k_small) 13 | yHat_big = regression.lwlrTest(xArr, xArr, yArr, k_big) 14 | re = regression.rssError(yArr, yHat) 15 | re_small = regression.rssError(yArr, yHat_small) 16 | re_big = regression.rssError(yArr, yHat_big) 17 | if re_small > re and re_big > re: 18 | k_big = k + (k_big - k) / 2.0 19 | k_small = k_small + (k - k_small) / 2.0 20 | elif re_small > re and re_big < re: 21 | k_small = k 22 | k = (k_big + k_small) / 2.0 23 | elif re_small < re and re_big > re: 24 | k_big = k 25 | k = (k_big + k_small) / 2.0 26 | else: 27 | k_big = k + (k_big - k) / 2.0 28 | k_small = k_small + (k - k_small) / 2.0 29 | if k_big - k_small < 0.01: 30 | k = k_small 31 | break 32 | return k 33 | 34 | 35 | start_count = 10 36 | sum_rate = 0.0 37 | count = 0 38 | 39 | mothed = 1 40 | if mothed == 0: 41 | xArr, yArr = regression.loadDataSet("foo.txt") 42 | k = best_k(xArr, yArr) 43 | yHat = regression.lwlrTest(xArr, xArr, yArr, k) 44 | print(k) 45 | else: 46 | xArr_origin, yArr_origin = regression.loadDataSet("foo.txt") 47 | # print(yArr_origin) 48 | xArr = [] 49 | yArr = [] 50 | m = (shape(xArr_origin))[0] 51 | yHat = zeros(m) 52 | 53 | xArr.append(xArr_origin[0][:]) 54 | yArr.append(yArr_origin[0]) 55 | yHat[0] = yArr_origin[0] 56 | 57 | for i in range(1, m): 58 | # k = best_k(xArr, yArr) 59 | k = 0.06830078125 60 | x = xArr_origin[i][:] 61 | y = regression.lwlr(x, xArr, yArr, k) 62 | # print(y.flatten().A[0][0]) 63 | yHat[i] = y.flatten().A[0][0] 64 | while yHat[i] <= 0: 65 | k = k + 0.01 66 | y = regression.lwlr(x, xArr, yArr, k) 67 | yHat[i] = y.flatten().A[0][0] 68 | xArr.append(x) 69 | yArr.append(yArr_origin[i]) 70 | print(i, k, yHat[i], yArr[i]) 71 | with open('workfile', 'a') as f: 72 | f.write(str(i)) 73 | f.write("\t") 74 | f.write(str(k)) 75 | f.write("\t") 76 | f.write(str(yHat[i])) 77 | f.write("\t") 78 | f.write(str(yArr[i])) 79 | f.write("\t") 80 | rate = (yHat[i] * 1.0 - yArr[i] * 1.0) ** 2 / yArr[i] 81 | f.write(str(rate)) 82 | f.write("\n") 83 | if i > sum_rate: 84 | sum_rate += rate 85 | count += 1 86 | # print(yArr) # k = best_k(xArr, yArr) 87 | # yHat = regression.lwlrTest(xArr, xArr, yArr, k) 88 | # print(yHat) 89 | # print(regression.rssError(yArr, yHat)) 90 | print(sum_rate * 1.0 / count) 91 | # print(yArr) 92 | # print(yHat) 93 | xMat = mat(xArr) 94 | srtInd = xMat[:, 0].argsort(0) 95 | # print(srtInd) 96 | # print(yHat[srtInd]) 97 | xSort = xMat[srtInd][:, 0, :] 98 | fig = plt.figure() 99 | ax = fig.add_subplot(111) 100 | ax.plot(xSort[:, 0], yHat[srtInd]) 101 | ax.scatter(xMat[:, 0].flatten().A[0], mat(yArr).T.flatten().A[0], s=2, c="red") 102 | plt.show() 103 | -------------------------------------------------------------------------------- /machinelearning/demo/foo.txt: -------------------------------------------------------------------------------- 1 | 1 41 2 | 2 41 3 | 3 42 4 | 4 46 5 | 5 43 6 | 6 42 7 | 7 42 8 | 8 42 9 | 9 44 10 | 10 44 11 | 11 42 12 | 12 38 13 | 13 35 14 | 14 33 15 | 15 33 16 | 16 33 17 | 17 32 18 | 18 32 19 | 19 33 20 | 20 34 21 | 21 35 22 | 22 38 23 | 23 39 24 | 24 39 25 | 25 41 26 | 26 42 27 | 27 42 28 | 28 46 29 | 29 44 30 | 30 43 31 | 31 43 32 | 32 43 33 | 33 44 34 | 34 44 35 | 35 42 36 | 36 38 37 | 37 34 38 | 38 32 39 | 39 32 40 | 40 32 41 | 41 32 42 | 42 32 43 | 43 34 44 | 44 34 45 | 45 35 46 | 46 38 47 | 47 39 48 | 48 40 49 | 49 40 50 | 50 41 51 | 51 41 52 | 52 45 53 | 53 43 54 | 54 41 55 | 55 41 56 | 56 41 57 | 57 43 58 | 58 43 59 | 59 40 60 | 60 36 61 | 61 33 62 | 62 31 63 | 63 31 64 | 64 31 65 | 65 31 66 | 66 32 67 | 67 33 68 | 68 33 69 | 69 34 70 | 70 37 71 | 71 39 72 | 72 39 73 | 73 39 74 | 74 39 75 | 75 39 76 | 76 43 77 | 77 41 78 | 78 40 79 | 79 40 80 | 80 40 81 | 81 41 82 | 82 41 83 | 83 39 84 | 84 35 85 | 85 32 86 | 86 30 87 | 87 29 88 | 88 29 89 | 89 31 90 | 90 31 91 | 91 32 92 | 92 32 93 | 93 34 94 | 94 37 95 | 95 38 96 | 96 38 97 | 97 38 98 | 98 38 99 | 99 38 100 | 100 42 101 | 101 40 102 | 102 39 103 | 103 39 104 | 104 39 105 | 105 41 106 | 106 41 107 | 107 38 108 | 108 35 109 | 109 31 110 | 110 29 111 | 111 29 112 | 112 29 113 | 113 29 114 | 114 30 115 | 115 31 116 | 116 31 117 | 117 32 118 | 118 35 119 | 119 36 120 | 120 37 121 | 121 36 122 | 122 37 123 | 123 37 124 | 124 41 125 | 125 38 126 | 126 37 127 | 127 37 128 | 128 37 129 | 129 39 130 | 130 39 131 | 131 37 132 | 132 33 133 | 133 30 134 | 134 28 135 | 135 27 136 | 136 27 137 | 137 27 138 | 138 30 139 | 139 31 140 | 140 31 141 | 141 31 142 | 142 34 143 | 143 35 144 | 144 35 145 | 145 36 146 | 146 37 147 | 147 38 148 | 148 41 149 | 149 39 150 | 150 38 151 | 151 38 152 | 152 38 153 | 153 40 154 | 154 40 155 | 155 38 156 | 156 33 157 | 157 30 158 | 158 28 159 | 159 27 160 | 160 27 161 | 161 27 162 | 162 26 163 | 163 27 164 | 164 27 165 | 165 29 166 | 166 32 167 | 167 34 168 | 168 35 169 | 169 37 170 | 170 38 171 | 171 39 172 | 172 42 173 | 173 41 174 | 174 39 175 | 175 39 176 | 176 39 177 | 177 41 178 | 178 41 179 | 179 39 180 | 180 34 181 | 181 30 182 | 182 28 183 | 183 28 184 | 184 28 185 | 185 27 186 | 186 27 187 | 187 27 188 | 188 28 189 | 189 29 190 | 190 33 191 | 191 35 192 | 192 36 193 | 193 38 194 | 194 39 195 | 195 40 196 | 196 43 197 | 197 41 198 | 198 40 199 | 199 40 200 | 200 40 201 | 201 41 202 | 202 41 203 | 203 39 204 | 204 33 205 | 205 30 206 | 206 27 207 | 207 27 208 | 208 27 209 | 209 27 210 | 210 27 211 | 211 28 212 | 212 28 213 | 213 30 214 | 214 34 215 | 215 35 216 | 216 36 217 | 217 36 218 | 218 38 219 | 219 39 220 | 220 42 221 | 221 40 222 | 222 39 223 | 223 39 224 | 224 39 225 | 225 40 226 | 226 40 227 | 227 38 228 | 228 34 229 | 229 30 230 | 230 28 231 | 231 27 232 | 232 27 233 | 233 28 234 | 234 27 235 | 235 27 236 | 236 27 237 | 237 29 238 | 238 33 239 | 239 34 240 | 240 35 241 | 241 37 242 | 242 38 243 | 243 39 244 | 244 42 245 | 245 40 246 | 246 39 247 | 247 38 248 | 248 38 249 | 249 40 250 | 250 40 251 | 251 38 252 | 252 33 253 | 253 30 254 | 254 28 255 | 255 27 256 | 256 27 257 | 257 28 258 | 258 27 259 | 259 27 260 | 260 28 261 | 261 29 262 | 262 33 263 | 263 35 264 | 264 36 265 | 265 36 266 | 266 37 267 | 267 37 268 | 268 41 269 | 269 39 270 | 270 38 271 | 271 38 272 | 272 37 273 | 273 39 274 | 274 40 275 | 275 37 276 | 276 33 277 | 277 29 278 | 278 27 279 | 279 27 280 | 280 27 281 | 281 28 282 | 282 27 283 | 283 28 284 | 284 28 285 | 285 29 286 | 286 32 287 | 287 34 288 | 288 34 289 | 289 35 290 | 290 36 291 | 291 37 292 | 292 40 293 | 293 39 294 | 294 37 295 | 295 37 296 | 296 37 297 | 297 39 298 | 298 39 299 | 299 37 300 | 300 33 301 | 301 29 302 | 302 27 303 | 303 26 304 | 304 27 305 | 305 27 306 | 306 27 307 | 307 28 308 | 308 28 309 | 309 29 310 | 310 32 311 | 311 33 312 | 312 34 -------------------------------------------------------------------------------- /machinelearning/demo/regression.py: -------------------------------------------------------------------------------- 1 | from numpy import * 2 | 3 | 4 | def loadDataSet(fileName): 5 | numFeat = len(open(fileName).readline().split('\t')) - 1 6 | dataMat = [] 7 | labelMat = [] 8 | fr = open(fileName) 9 | for line in fr.readlines(): 10 | lineArr = [] 11 | curLine = line.strip().split('\t') 12 | for i in range(numFeat): 13 | lineArr.append(float(curLine[i])) 14 | dataMat.append(lineArr) 15 | labelMat.append(float(curLine[-1])) 16 | return dataMat, labelMat 17 | 18 | 19 | def standRegress(xArr, yArr): 20 | xMat = mat(xArr) 21 | yMat = mat(yArr).T 22 | xTx = xMat.T * xMat 23 | if linalg.det(xTx) == 0.0: 24 | print("standRegress : This matrix is sigular, cannot do inverse") 25 | ws = xTx.I * (xMat.T * yMat) 26 | return ws 27 | 28 | 29 | def lwlr(testPoint, xArr, yArr, k=1.0): 30 | xMat = mat(xArr) 31 | yMat = mat(yArr).T 32 | m = shape(xMat)[0] 33 | weights = mat(eye((m))) 34 | for j in range(m): 35 | diffMat = testPoint - xMat[j, :] 36 | weights[j, j] = exp(diffMat * diffMat.T / (-2.0 * k ** 2)) 37 | xTx = xMat.T * (weights * xMat) 38 | if linalg.det(xTx) == 0.0: 39 | print("lwlr : This matrix is singular,cannot do inverse") 40 | return 41 | ws = xTx.I * (xMat.T * (weights * yMat)) 42 | return testPoint * ws 43 | 44 | 45 | def lwlrTest(testArr, xArr, yArr, k=1.0): 46 | m = shape(testArr)[0] 47 | yHat = zeros(m) 48 | #print(yHat) 49 | for i in range(m): 50 | yHat[i] = lwlr(testArr[i], xArr, yArr, k) 51 | return yHat 52 | 53 | def rssError(yArr,yHatArr): 54 | return ((yArr-yHatArr)**2).sum() -------------------------------------------------------------------------------- /machinelearning/demo/workfile: -------------------------------------------------------------------------------- 1 | 1 1.0011132812499999 82.0 41.0 1.0 2 | 2 0.06830078125 61.5 42.0 0.464285714286 3 | 3 0.06830078125 56.0 46.0 0.217391304348 4 | 4 0.06830078125 57.5 43.0 0.337209302326 5 | 5 0.06830078125 51.6 42.0 0.228571428571 6 | 6 0.06830078125 49.0 42.0 0.166666666667 7 | 7 0.06830078125 48.0 42.0 0.142857142857 8 | 8 0.06830078125 47.25 44.0 0.0738636363636 9 | 9 0.06830078125 48.8888888889 44.0 0.111111111111 10 | 10 0.06830078125 48.4 42.0 0.152380952381 11 | 11 0.06830078125 45.8181818182 38.0 0.205741626794 12 | 12 0.06830078125 41.1666666667 35.0 0.17619047619 13 | 13 0.06830078125 37.6923076923 33.0 0.142191142191 14 | 14 0.06830078125 35.3571428571 33.0 0.0714285714286 15 | 15 0.06830078125 35.2 33.0 0.0666666666667 16 | 16 0.06830078125 35.0625 32.0 0.095703125 17 | 17 0.06830078125 33.8823529412 32.0 0.0588235294118 18 | 18 0.06830078125 33.7777777778 33.0 0.023569023569 19 | 19 0.06830078125 34.7368421053 34.0 0.0216718266254 20 | 20 0.06830078125 35.7 35.0 0.02 21 | 21 0.06830078125 36.6666666667 38.0 0.0350877192982 22 | 22 0.06830078125 39.7272727273 39.0 0.018648018648 23 | 23 0.06830078125 40.6956521739 39.0 0.0434782608696 24 | 24 0.06830078125 40.625 41.0 0.00914634146341 25 | 25 0.06830078125 42.64 42.0 0.0152380952381 26 | 26 0.06830078125 43.6153846154 42.0 0.0384615384615 27 | 27 0.06830078125 43.5555555556 46.0 0.0531400966184 28 | 28 0.06830078125 47.6428571429 44.0 0.0827922077922 29 | 29 0.06830078125 45.5172413793 43.0 0.0585404971933 30 | 30 0.06830078125 44.4333333333 43.0 0.0333333333333 31 | 31 0.06830078125 44.3870967742 43.0 0.0322580645161 32 | 32 0.06830078125 44.34375 44.0 0.0078125 33 | 33 0.06830078125 45.3333333333 44.0 0.030303030303 34 | 34 0.06830078125 45.2941176471 42.0 0.078431372549 35 | 35 0.06830078125 43.2 38.0 0.136842105263 36 | 36 0.06830078125 39.0555555556 34.0 0.148692810458 37 | 37 0.06830078125 34.9189189189 32.0 0.0912162162162 38 | 38 0.06830078125 32.8421052632 32.0 0.0263157894737 39 | 39 0.06830078125 32.8205128205 32.0 0.025641025641 40 | 40 0.06830078125 32.8 32.0 0.025 41 | 41 0.06830078125 32.7804878049 32.0 0.0243902439024 42 | 42 0.06830078125 32.7619047619 34.0 0.0364145658263 43 | 43 0.06830078125 34.7906976744 34.0 0.0232558139535 44 | 44 0.06830078125 34.7727272727 35.0 0.00649350649351 45 | 45 0.06830078125 35.7777777778 38.0 0.0584795321637 46 | 46 0.06830078125 38.8260869565 39.0 0.00445930880713 47 | 47 0.06830078125 39.829787234 40.0 0.00425531914894 48 | 48 0.06830078125 40.8333333333 40.0 0.0208333333333 49 | 49 0.06830078125 40.8163265306 41.0 0.00447984071677 50 | 50 0.06830078125 41.82 41.0 0.02 51 | 51 0.06830078125 41.8039215686 45.0 0.0710239651416 52 | 52 0.06830078125 45.8653846154 43.0 0.0666368515206 53 | 53 0.06830078125 43.8113207547 41.0 0.0685687988955 54 | 54 0.06830078125 41.7592592593 41.0 0.0185185185185 55 | 55 0.06830078125 41.7454545455 41.0 0.0181818181818 56 | 56 0.06830078125 41.7321428571 43.0 0.0294850498339 57 | 57 0.06830078125 43.7543859649 43.0 0.0175438596491 58 | 58 0.06830078125 43.7413793103 40.0 0.0935344827586 59 | 59 0.06830078125 40.6779661017 36.0 0.129943502825 60 | 60 0.06830078125 36.6 33.0 0.109090909091 61 | 61 0.06830078125 33.5409836066 31.0 0.0819672131148 62 | 62 0.06830078125 31.5 31.0 0.0161290322581 63 | 63 0.06830078125 31.4920634921 31.0 0.015873015873 64 | 64 0.06830078125 31.484375 31.0 0.015625 65 | 65 0.06830078125 31.4769230769 32.0 0.0163461538462 66 | 66 0.06830078125 32.4848484848 33.0 0.0156106519743 67 | 67 0.06830078125 33.4925373134 33.0 0.0149253731343 68 | 68 0.06830078125 33.4852941176 34.0 0.0151384083045 69 | 69 0.06830078125 34.4927536232 37.0 0.0677634155895 70 | 70 0.06830078125 37.5285714286 39.0 0.0377289377289 71 | 71 0.06830078125 39.5492957746 39.0 0.0140845070423 72 | 72 0.06830078125 39.5416666667 39.0 0.0138888888889 73 | 73 0.06830078125 39.5342465753 39.0 0.013698630137 74 | 74 0.06830078125 39.527027027 39.0 0.0135135135135 75 | 75 0.06830078125 39.52 43.0 0.0809302325581 76 | 76 0.06830078125 43.5657894737 41.0 0.0625802310655 77 | 77 0.06830078125 41.5324675325 40.0 0.0383116883117 78 | 78 0.06830078125 40.5128205128 40.0 0.0128205128205 79 | 79 0.06830078125 40.5063291139 40.0 0.0126582278481 80 | 80 0.06830078125 40.5 41.0 0.0121951219512 81 | 81 0.06830078125 41.5061728395 41.0 0.0123456790123 82 | 82 0.06830078125 41.5 39.0 0.0641025641026 83 | 83 0.06830078125 39.4698795181 35.0 0.127710843373 84 | 84 0.06830078125 35.4166666667 32.0 0.106770833333 85 | 85 0.06830078125 32.3764705882 30.0 0.0792156862745 86 | 86 0.06830078125 30.3488372093 29.0 0.046511627907 87 | 87 0.06830078125 29.3333333333 29.0 0.0114942528736 88 | 88 0.06830078125 29.3295454545 31.0 0.0538856304985 89 | 89 0.06830078125 31.3483146067 31.0 0.0112359550562 90 | 90 0.06830078125 31.3444444444 32.0 0.0204861111111 91 | 91 0.06830078125 32.3516483516 32.0 0.010989010989 92 | 92 0.06830078125 32.347826087 34.0 0.0485933503836 93 | 93 0.06830078125 34.3655913978 37.0 0.0712002324906 94 | 94 0.06830078125 37.3936170213 38.0 0.0159574468085 95 | 95 0.06830078125 38.4 38.0 0.0105263157895 96 | 96 0.06830078125 38.3958333333 38.0 0.0104166666667 97 | 97 0.06830078125 38.3917525773 38.0 0.0103092783505 98 | 98 0.06830078125 38.387755102 38.0 0.0102040816327 99 | 99 0.06830078125 38.3838383838 42.0 0.0860990860991 100 | 100 0.06830078125 42.42 40.0 0.0605 101 | 101 0.06830078125 40.396039604 39.0 0.035795887281 102 | 102 0.06830078125 39.3823529412 39.0 0.00980392156863 103 | 103 0.06830078125 39.3786407767 39.0 0.00970873786408 104 | 104 0.06830078125 39.375 41.0 0.0396341463415 105 | 105 0.06830078125 41.3904761905 41.0 0.00952380952381 106 | 106 0.06830078125 41.3867924528 38.0 0.0891261171797 107 | 107 0.06830078125 38.3551401869 35.0 0.0958611481976 108 | 108 0.06830078125 35.3240740741 31.0 0.139486260454 109 | 109 0.06830078125 31.2844036697 29.0 0.0787725403353 110 | 110 0.06830078125 29.2636363636 29.0 0.00909090909091 111 | 111 0.06830078125 29.2612612613 29.0 0.00900900900901 112 | 112 0.06830078125 29.2589285714 29.0 0.00892857142857 113 | 113 0.06830078125 29.2566371681 30.0 0.0247787610619 114 | 114 0.06830078125 30.2631578947 31.0 0.0237691001698 115 | 115 0.06830078125 31.2695652174 31.0 0.00869565217391 116 | 116 0.06830078125 31.2672413793 32.0 0.0228987068966 117 | 117 0.06830078125 32.2735042735 35.0 0.0778998778999 118 | 118 0.06830078125 35.2966101695 36.0 0.019538606403 119 | 119 0.06830078125 36.3025210084 37.0 0.0188507835567 120 | 120 0.06830078125 37.3083333333 36.0 0.0363425925926 121 | 121 0.06830078125 36.2975206612 37.0 0.0189859280768 122 | 122 0.06830078125 37.3032786885 37.0 0.00819672131148 123 | 123 0.06830078125 37.3008130081 41.0 0.0902240729724 124 | 124 0.06830078125 41.3306451613 38.0 0.0876485568761 125 | 125 0.06830078125 38.304 37.0 0.0352432432432 126 | 126 0.06830078125 37.2936507937 37.0 0.00793650793651 127 | 127 0.06830078125 37.2913385827 37.0 0.00787401574803 128 | 128 0.06830078125 37.2890625 39.0 0.0438701923077 129 | 129 0.06830078125 39.3023255814 39.0 0.0077519379845 130 | 130 0.06830078125 39.3 37.0 0.0621621621622 131 | 131 0.06830078125 37.2824427481 33.0 0.129770992366 132 | 132 0.06830078125 33.25 30.0 0.108333333333 133 | 133 0.06830078125 30.2255639098 28.0 0.0794844253491 134 | 134 0.06830078125 28.2089552239 27.0 0.044776119403 135 | 135 0.06830078125 27.2 27.0 0.00740740740741 136 | 136 0.06830078125 27.1985294118 27.0 0.00735294117647 137 | 137 0.06830078125 27.197080292 30.0 0.0934306569343 138 | 138 0.06830078125 30.2173913043 31.0 0.0252454417952 139 | 139 0.06830078125 31.2230215827 31.0 0.00719424460432 140 | 140 0.06830078125 31.2214285714 31.0 0.00714285714286 141 | 141 0.06830078125 31.219858156 34.0 0.0817688777639 142 | 142 0.06830078125 34.2394366197 35.0 0.0217303822938 143 | 143 0.06830078125 35.2447552448 35.0 0.00699300699301 144 | 144 0.06830078125 35.2430555556 36.0 0.0210262345679 145 | 145 0.06830078125 36.2482758621 37.0 0.0203168685927 146 | 146 0.06830078125 37.2534246575 38.0 0.0196467195386 147 | 147 0.06830078125 38.2585034014 41.0 0.0668657706985 148 | 148 0.06830078125 41.277027027 39.0 0.0583853083853 149 | 149 0.06830078125 39.2617449664 38.0 0.0332038149064 150 | 150 0.06830078125 38.2533333333 38.0 0.00666666666667 151 | 151 0.06830078125 38.2516556291 38.0 0.00662251655629 152 | 152 0.06830078125 38.25 40.0 0.04375 153 | 153 0.06830078125 40.2614379085 40.0 0.00653594771242 154 | 154 0.06830078125 40.2597402597 38.0 0.0594668489405 155 | 155 0.06830078125 38.2451612903 33.0 0.158944281525 156 | 156 0.06830078125 33.2115384615 30.0 0.107051282051 157 | 157 0.06830078125 30.1910828025 28.0 0.0782529572338 158 | 158 0.06830078125 28.1772151899 27.0 0.0436005625879 159 | 159 0.06830078125 27.1698113208 27.0 0.0062893081761 160 | 160 0.06830078125 27.16875 27.0 0.00625 161 | 161 0.06830078125 27.1677018634 26.0 0.044911610129 162 | 162 0.06830078125 26.1604938272 27.0 0.0310928212163 163 | 163 0.06830078125 27.1656441718 27.0 0.00613496932515 164 | 164 0.06830078125 27.1646341463 29.0 0.0632884777124 165 | 165 0.06830078125 29.1757575758 32.0 0.0882575757576 166 | 166 0.06830078125 32.1927710843 34.0 0.0531537916371 167 | 167 0.06830078125 34.2035928144 35.0 0.022754491018 168 | 168 0.06830078125 35.2083333333 37.0 0.0484234234234 169 | 169 0.06830078125 37.2189349112 38.0 0.020554344441 170 | 170 0.06830078125 38.2235294118 39.0 0.0199095022624 171 | 171 0.06830078125 39.2280701754 42.0 0.0659983291562 172 | 172 0.06830078125 42.2441860465 41.0 0.0303460011344 173 | 173 0.06830078125 41.2369942197 39.0 0.057358826145 174 | 174 0.06830078125 39.224137931 39.0 0.00574712643678 175 | 175 0.06830078125 39.2228571429 39.0 0.00571428571429 176 | 176 0.06830078125 39.2215909091 41.0 0.0433758314856 177 | 177 0.06830078125 41.2316384181 41.0 0.00564971751412 178 | 178 0.06830078125 41.2303370787 39.0 0.0571881302218 179 | 179 0.06830078125 39.217877095 34.0 0.153466973382 180 | 180 0.06830078125 34.1888888889 30.0 0.13962962963 181 | 181 0.06830078125 30.1657458564 28.0 0.0773480662983 182 | 182 0.06830078125 28.1538461538 28.0 0.00549450549451 183 | 183 0.06830078125 28.1530054645 28.0 0.00546448087432 184 | 184 0.06830078125 28.152173913 27.0 0.0426731078905 185 | 185 0.06830078125 27.1459459459 27.0 0.00540540540541 186 | 186 0.06830078125 27.1451612903 27.0 0.00537634408602 187 | 187 0.06830078125 27.1443850267 28.0 0.0305576776165 188 | 188 0.06830078125 28.1489361702 29.0 0.0293470286134 189 | 189 0.06830078125 29.1534391534 33.0 0.116562449896 190 | 190 0.06830078125 33.1736842105 35.0 0.0521804511278 191 | 191 0.06830078125 35.1832460733 36.0 0.022687609075 192 | 192 0.06830078125 36.1875 38.0 0.0476973684211 193 | 193 0.06830078125 38.1968911917 39.0 0.0205925335459 194 | 194 0.06830078125 39.2010309278 40.0 0.0199742268041 195 | 195 0.06830078125 40.2051282051 43.0 0.0649970184854 196 | 196 0.06830078125 43.2193877551 41.0 0.054131408661 197 | 197 0.06830078125 41.2081218274 40.0 0.0302030456853 198 | 198 0.06830078125 40.202020202 40.0 0.00505050505051 199 | 199 0.06830078125 40.2010050251 40.0 0.00502512562814 200 | 200 0.06830078125 40.2 41.0 0.019512195122 201 | 201 0.06830078125 41.2039800995 41.0 0.00497512437811 202 | 202 0.06830078125 41.202970297 39.0 0.0564864178726 203 | 203 0.06830078125 39.1921182266 33.0 0.187639946261 204 | 204 0.06830078125 33.1617647059 30.0 0.105392156863 205 | 205 0.06830078125 30.1463414634 27.0 0.116531165312 206 | 206 0.06830078125 27.1310679612 27.0 0.00485436893204 207 | 207 0.06830078125 27.1304347826 27.0 0.0048309178744 208 | 208 0.06830078125 27.1298076923 27.0 0.00480769230769 209 | 209 0.06830078125 27.1291866029 27.0 0.00478468899522 210 | 210 0.06830078125 27.1285714286 28.0 0.0311224489796 211 | 211 0.06830078125 28.1327014218 28.0 0.00473933649289 212 | 212 0.06830078125 28.1320754717 30.0 0.0622641509434 213 | 213 0.06830078125 30.1408450704 34.0 0.113504556752 214 | 214 0.06830078125 34.1588785047 35.0 0.0240320427236 215 | 215 0.06830078125 35.1627906977 36.0 0.0232558139535 216 | 216 0.06830078125 36.1666666667 36.0 0.00462962962963 217 | 217 0.06830078125 36.1658986175 38.0 0.048265825855 218 | 218 0.06830078125 38.1743119266 39.0 0.0211714890614 219 | 219 0.06830078125 39.1780821918 42.0 0.0671885192433 220 | 220 0.06830078125 42.1909090909 40.0 0.0547727272727 221 | 221 0.06830078125 40.1809954751 39.0 0.0302819352593 222 | 222 0.06830078125 39.1756756757 39.0 0.0045045045045 223 | 223 0.06830078125 39.1748878924 39.0 0.00448430493274 224 | 224 0.06830078125 39.1741071429 40.0 0.0206473214286 225 | 225 0.06830078125 40.1777777778 40.0 0.00444444444444 226 | 226 0.06830078125 40.1769911504 38.0 0.0572892408011 227 | 227 0.06830078125 38.1674008811 34.0 0.122570614149 228 | 228 0.06830078125 34.149122807 30.0 0.138304093567 229 | 229 0.06830078125 30.1310043668 28.0 0.0761072988147 230 | 230 0.06830078125 28.1217391304 27.0 0.0415458937198 231 | 231 0.06830078125 27.1168831169 27.0 0.004329004329 232 | 232 0.06830078125 27.1163793103 28.0 0.0315578817734 233 | 233 0.06830078125 28.1201716738 27.0 0.0414878397711 234 | 234 0.06830078125 27.1153846154 27.0 0.0042735042735 235 | 235 0.06830078125 27.114893617 27.0 0.00425531914894 236 | 236 0.06830078125 27.1144067797 29.0 0.0650204558738 237 | 237 0.06830078125 29.1223628692 33.0 0.117504155479 238 | 238 0.06830078125 33.1386554622 34.0 0.0253336628769 239 | 239 0.06830078125 34.1422594142 35.0 0.0245068738793 240 | 240 0.06830078125 35.1458333333 37.0 0.0501126126126 241 | 241 0.06830078125 37.153526971 38.0 0.0222756060275 242 | 242 0.06830078125 38.1570247934 39.0 0.0216147488875 243 | 243 0.06830078125 39.1604938272 42.0 0.0676072898295 244 | 244 0.06830078125 42.1721311475 40.0 0.0543032786885 245 | 245 0.06830078125 40.1632653061 39.0 0.0298273155416 246 | 246 0.06830078125 39.1585365854 38.0 0.030487804878 247 | 247 0.06830078125 38.1538461538 38.0 0.00404858299595 248 | 248 0.06830078125 38.1532258065 40.0 0.0461693548387 249 | 249 0.06830078125 40.1606425703 40.0 0.00401606425703 250 | 250 0.06830078125 40.16 38.0 0.0568421052632 251 | 251 0.06830078125 38.1513944223 33.0 0.156102861282 252 | 252 0.06830078125 33.130952381 30.0 0.104365079365 253 | 253 0.06830078125 30.1185770751 28.0 0.0756634669678 254 | 254 0.06830078125 28.1102362205 27.0 0.0411198600175 255 | 255 0.06830078125 27.1058823529 27.0 0.00392156862745 256 | 256 0.06830078125 27.10546875 28.0 0.0319475446429 257 | 257 0.06830078125 28.1089494163 27.0 0.0410722006053 258 | 258 0.06830078125 27.1046511628 27.0 0.00387596899225 259 | 259 0.06830078125 27.1042471042 28.0 0.0319911748483 260 | 260 0.06830078125 28.1076923077 29.0 0.0307692307692 261 | 261 0.06830078125 29.1111111111 33.0 0.117845117845 262 | 262 0.06830078125 33.1259541985 35.0 0.0535441657579 263 | 263 0.06830078125 35.1330798479 36.0 0.0240811153359 264 | 264 0.06830078125 36.1363636364 36.0 0.00378787878788 265 | 265 0.06830078125 36.1358490566 37.0 0.0233554309026 266 | 266 0.06830078125 37.1390977444 37.0 0.00375939849624 267 | 267 0.06830078125 37.138576779 41.0 0.0941810541701 268 | 268 0.06830078125 41.1529850746 39.0 0.0552047455033 269 | 269 0.06830078125 39.1449814126 38.0 0.0301310898063 270 | 270 0.06830078125 38.1407407407 38.0 0.0037037037037 271 | 271 0.06830078125 38.1402214022 37.0 0.0308167946544 272 | 272 0.06830078125 37.1360294118 39.0 0.0477941176471 273 | 273 0.06830078125 39.1428571429 40.0 0.0214285714286 274 | 274 0.06830078125 40.1459854015 37.0 0.0850266324719 275 | 275 0.06830078125 37.1345454545 33.0 0.125289256198 276 | 276 0.06830078125 33.1195652174 29.0 0.142053973013 277 | 277 0.06830078125 29.1046931408 27.0 0.0779515978072 278 | 278 0.06830078125 27.0971223022 27.0 0.00359712230216 279 | 279 0.06830078125 27.0967741935 27.0 0.00358422939068 280 | 280 0.06830078125 27.0964285714 28.0 0.0322704081633 281 | 281 0.06830078125 28.0996441281 27.0 0.0407275603005 282 | 282 0.06830078125 27.0957446809 28.0 0.0322948328267 283 | 283 0.06830078125 28.0989399293 28.0 0.00353356890459 284 | 284 0.06830078125 28.0985915493 29.0 0.0310830500243 285 | 285 0.06830078125 29.101754386 32.0 0.0905701754386 286 | 286 0.06830078125 32.1118881119 34.0 0.0555327025915 287 | 287 0.06830078125 34.118466899 34.0 0.00348432055749 288 | 288 0.06830078125 34.1180555556 35.0 0.0251984126984 289 | 289 0.06830078125 35.1211072664 36.0 0.0244136870434 290 | 290 0.06830078125 36.124137931 37.0 0.0236719478099 291 | 291 0.06830078125 37.1271477663 40.0 0.0718213058419 292 | 292 0.06830078125 40.1369863014 39.0 0.0291534949069 293 | 293 0.06830078125 39.133105802 37.0 0.0576515081635 294 | 294 0.06830078125 37.1258503401 37.0 0.00340136054422 295 | 295 0.06830078125 37.1254237288 37.0 0.00338983050847 296 | 296 0.06830078125 37.125 39.0 0.0480769230769 297 | 297 0.06830078125 39.1313131313 39.0 0.003367003367 298 | 298 0.06830078125 39.1308724832 37.0 0.0575911481952 299 | 299 0.06830078125 37.1237458194 33.0 0.124961994527 300 | 300 0.06830078125 33.11 29.0 0.141724137931 301 | 301 0.06830078125 29.096345515 27.0 0.0776424264796 302 | 302 0.06830078125 27.0894039735 26.0 0.0419001528273 303 | 303 0.06830078125 26.0858085809 27.0 0.0338589414497 304 | 304 0.06830078125 27.0888157895 27.0 0.00328947368421 305 | 305 0.06830078125 27.0885245902 27.0 0.00327868852459 306 | 306 0.06830078125 27.0882352941 28.0 0.0325630252101 307 | 307 0.06830078125 28.0912052117 28.0 0.00325732899023 308 | 308 0.06830078125 28.0909090909 29.0 0.0313479623824 309 | 309 0.06830078125 29.0938511327 32.0 0.0908171521036 310 | 310 0.06830078125 32.1032258065 33.0 0.0271749755621 311 | 311 0.06830078125 33.1061093248 34.0 0.026290902213 312 | 1 0.06830078125 82.0 41.0 1.0 313 | 2 0.06830078125 61.5 42.0 0.464285714286 314 | 3 0.06830078125 56.0 46.0 0.217391304348 315 | 4 0.06830078125 57.5 43.0 0.337209302326 316 | 5 0.06830078125 51.6 42.0 0.228571428571 317 | 6 0.06830078125 49.0 42.0 0.166666666667 318 | 7 0.06830078125 48.0 42.0 0.142857142857 319 | 8 0.06830078125 47.25 44.0 0.0738636363636 320 | 9 0.06830078125 48.8888888889 44.0 0.111111111111 321 | 10 0.06830078125 48.4 42.0 0.152380952381 322 | 11 0.06830078125 45.8181818182 38.0 0.205741626794 323 | 12 0.06830078125 41.1666666667 35.0 0.17619047619 324 | 13 0.06830078125 37.6923076923 33.0 0.142191142191 325 | 14 0.06830078125 35.3571428571 33.0 0.0714285714286 326 | 15 0.06830078125 35.2 33.0 0.0666666666667 327 | 16 0.06830078125 35.0625 32.0 0.095703125 328 | 17 0.06830078125 33.8823529412 32.0 0.0588235294118 329 | 18 0.06830078125 33.7777777778 33.0 0.023569023569 330 | 19 0.06830078125 34.7368421053 34.0 0.0216718266254 331 | 20 0.06830078125 35.7 35.0 0.02 332 | 21 0.06830078125 36.6666666667 38.0 0.0350877192982 333 | 22 0.06830078125 39.7272727273 39.0 0.018648018648 334 | 23 0.06830078125 40.6956521739 39.0 0.0434782608696 335 | 24 0.06830078125 40.625 41.0 0.00914634146341 336 | 25 0.06830078125 42.64 42.0 0.0152380952381 337 | 26 0.06830078125 43.6153846154 42.0 0.0384615384615 338 | 27 0.06830078125 43.5555555556 46.0 0.0531400966184 339 | 28 0.06830078125 47.6428571429 44.0 0.0827922077922 340 | 29 0.06830078125 45.5172413793 43.0 0.0585404971933 341 | 30 0.06830078125 44.4333333333 43.0 0.0333333333333 342 | 31 0.06830078125 44.3870967742 43.0 0.0322580645161 343 | 32 0.06830078125 44.34375 44.0 0.0078125 344 | 33 0.06830078125 45.3333333333 44.0 0.030303030303 345 | 34 0.06830078125 45.2941176471 42.0 0.078431372549 346 | 35 0.06830078125 43.2 38.0 0.136842105263 347 | 36 0.06830078125 39.0555555556 34.0 0.148692810458 348 | 37 0.06830078125 34.9189189189 32.0 0.0912162162162 349 | 38 0.06830078125 32.8421052632 32.0 0.0263157894737 350 | 39 0.06830078125 32.8205128205 32.0 0.025641025641 351 | 40 0.06830078125 32.8 32.0 0.025 352 | 41 0.06830078125 32.7804878049 32.0 0.0243902439024 353 | 42 0.06830078125 32.7619047619 34.0 0.0364145658263 354 | 43 0.06830078125 34.7906976744 34.0 0.0232558139535 355 | 44 0.06830078125 34.7727272727 35.0 0.00649350649351 356 | 45 0.06830078125 35.7777777778 38.0 0.0584795321637 357 | 46 0.06830078125 38.8260869565 39.0 0.00445930880713 358 | 47 0.06830078125 39.829787234 40.0 0.00425531914894 359 | 48 0.06830078125 40.8333333333 40.0 0.0208333333333 360 | 49 0.06830078125 40.8163265306 41.0 0.00447984071677 361 | 50 0.06830078125 41.82 41.0 0.02 362 | 51 0.06830078125 41.8039215686 45.0 0.0710239651416 363 | 52 0.06830078125 45.8653846154 43.0 0.0666368515206 364 | 53 0.06830078125 43.8113207547 41.0 0.0685687988955 365 | 54 0.06830078125 41.7592592593 41.0 0.0185185185185 366 | 55 0.06830078125 41.7454545455 41.0 0.0181818181818 367 | 56 0.06830078125 41.7321428571 43.0 0.0294850498339 368 | 57 0.06830078125 43.7543859649 43.0 0.0175438596491 369 | 58 0.06830078125 43.7413793103 40.0 0.0935344827586 370 | 59 0.06830078125 40.6779661017 36.0 0.129943502825 371 | 60 0.06830078125 36.6 33.0 0.109090909091 372 | 61 0.06830078125 33.5409836066 31.0 0.0819672131148 373 | 62 0.06830078125 31.5 31.0 0.0161290322581 374 | 63 0.06830078125 31.4920634921 31.0 0.015873015873 375 | 64 0.06830078125 31.484375 31.0 0.015625 376 | 65 0.06830078125 31.4769230769 32.0 0.0163461538462 377 | 66 0.06830078125 32.4848484848 33.0 0.0156106519743 378 | 67 0.06830078125 33.4925373134 33.0 0.0149253731343 379 | 68 0.06830078125 33.4852941176 34.0 0.0151384083045 380 | 69 0.06830078125 34.4927536232 37.0 0.0677634155895 381 | 70 0.06830078125 37.5285714286 39.0 0.0377289377289 382 | 71 0.06830078125 39.5492957746 39.0 0.0140845070423 383 | 72 0.06830078125 39.5416666667 39.0 0.0138888888889 384 | 73 0.06830078125 39.5342465753 39.0 0.013698630137 385 | 74 0.06830078125 39.527027027 39.0 0.0135135135135 386 | 75 0.06830078125 39.52 43.0 0.0809302325581 387 | 76 0.06830078125 43.5657894737 41.0 0.0625802310655 388 | 77 0.06830078125 41.5324675325 40.0 0.0383116883117 389 | 78 0.06830078125 40.5128205128 40.0 0.0128205128205 390 | 79 0.06830078125 40.5063291139 40.0 0.0126582278481 391 | 80 0.06830078125 40.5 41.0 0.0121951219512 392 | 81 0.06830078125 41.5061728395 41.0 0.0123456790123 393 | 82 0.06830078125 41.5 39.0 0.0641025641026 394 | 83 0.06830078125 39.4698795181 35.0 0.127710843373 395 | 84 0.06830078125 35.4166666667 32.0 0.106770833333 396 | 85 0.06830078125 32.3764705882 30.0 0.0792156862745 397 | 86 0.06830078125 30.3488372093 29.0 0.046511627907 398 | 87 0.06830078125 29.3333333333 29.0 0.0114942528736 399 | 88 0.06830078125 29.3295454545 31.0 0.0538856304985 400 | 89 0.06830078125 31.3483146067 31.0 0.0112359550562 401 | 90 0.06830078125 31.3444444444 32.0 0.0204861111111 402 | 91 0.06830078125 32.3516483516 32.0 0.010989010989 403 | 92 0.06830078125 32.347826087 34.0 0.0485933503836 404 | 93 0.06830078125 34.3655913978 37.0 0.0712002324906 405 | 94 0.06830078125 37.3936170213 38.0 0.0159574468085 406 | 95 0.06830078125 38.4 38.0 0.0105263157895 407 | 96 0.06830078125 38.3958333333 38.0 0.0104166666667 408 | 97 0.06830078125 38.3917525773 38.0 0.0103092783505 409 | 98 0.06830078125 38.387755102 38.0 0.0102040816327 410 | 99 0.06830078125 38.3838383838 42.0 0.0860990860991 411 | 100 0.06830078125 42.42 40.0 0.0605 412 | 101 0.06830078125 40.396039604 39.0 0.035795887281 413 | 102 0.06830078125 39.3823529412 39.0 0.00980392156863 414 | 103 0.06830078125 39.3786407767 39.0 0.00970873786408 415 | 104 0.06830078125 39.375 41.0 0.0396341463415 416 | 105 0.06830078125 41.3904761905 41.0 0.00952380952381 417 | 106 0.06830078125 41.3867924528 38.0 0.0891261171797 418 | 107 0.06830078125 38.3551401869 35.0 0.0958611481976 419 | 108 0.06830078125 35.3240740741 31.0 0.139486260454 420 | 109 0.06830078125 31.2844036697 29.0 0.0787725403353 421 | 110 0.06830078125 29.2636363636 29.0 0.00909090909091 422 | 111 0.06830078125 29.2612612613 29.0 0.00900900900901 423 | 112 0.06830078125 29.2589285714 29.0 0.00892857142857 424 | 113 0.06830078125 29.2566371681 30.0 0.0247787610619 425 | 114 0.06830078125 30.2631578947 31.0 0.0237691001698 426 | 115 0.06830078125 31.2695652174 31.0 0.00869565217391 427 | 116 0.06830078125 31.2672413793 32.0 0.0228987068966 428 | 117 0.06830078125 32.2735042735 35.0 0.0778998778999 429 | 118 0.06830078125 35.2966101695 36.0 0.019538606403 430 | 119 0.06830078125 36.3025210084 37.0 0.0188507835567 431 | 120 0.06830078125 37.3083333333 36.0 0.0363425925926 432 | 121 0.06830078125 36.2975206612 37.0 0.0189859280768 433 | 122 0.06830078125 37.3032786885 37.0 0.00819672131148 434 | 123 0.06830078125 37.3008130081 41.0 0.0902240729724 435 | 124 0.06830078125 41.3306451613 38.0 0.0876485568761 436 | 125 0.06830078125 38.304 37.0 0.0352432432432 437 | 126 0.06830078125 37.2936507937 37.0 0.00793650793651 438 | 127 0.06830078125 37.2913385827 37.0 0.00787401574803 439 | 128 0.06830078125 37.2890625 39.0 0.0438701923077 440 | 129 0.06830078125 39.3023255814 39.0 0.0077519379845 441 | 130 0.06830078125 39.3 37.0 0.0621621621622 442 | 131 0.06830078125 37.2824427481 33.0 0.129770992366 443 | 132 0.06830078125 33.25 30.0 0.108333333333 444 | 133 0.06830078125 30.2255639098 28.0 0.0794844253491 445 | 134 0.06830078125 28.2089552239 27.0 0.044776119403 446 | 135 0.06830078125 27.2 27.0 0.00740740740741 447 | 136 0.06830078125 27.1985294118 27.0 0.00735294117647 448 | 137 0.06830078125 27.197080292 30.0 0.0934306569343 449 | 138 0.06830078125 30.2173913043 31.0 0.0252454417952 450 | 139 0.06830078125 31.2230215827 31.0 0.00719424460432 451 | 140 0.06830078125 31.2214285714 31.0 0.00714285714286 452 | 141 0.06830078125 31.219858156 34.0 0.0817688777639 453 | 142 0.06830078125 34.2394366197 35.0 0.0217303822938 454 | 143 0.06830078125 35.2447552448 35.0 0.00699300699301 455 | 144 0.06830078125 35.2430555556 36.0 0.0210262345679 456 | 145 0.06830078125 36.2482758621 37.0 0.0203168685927 457 | 146 0.06830078125 37.2534246575 38.0 0.0196467195386 458 | 147 0.06830078125 38.2585034014 41.0 0.0668657706985 459 | 148 0.06830078125 41.277027027 39.0 0.0583853083853 460 | 149 0.06830078125 39.2617449664 38.0 0.0332038149064 461 | 150 0.06830078125 38.2533333333 38.0 0.00666666666667 462 | 151 0.06830078125 38.2516556291 38.0 0.00662251655629 463 | 152 0.06830078125 38.25 40.0 0.04375 464 | 153 0.06830078125 40.2614379085 40.0 0.00653594771242 465 | 154 0.06830078125 40.2597402597 38.0 0.0594668489405 466 | 155 0.06830078125 38.2451612903 33.0 0.158944281525 467 | 156 0.06830078125 33.2115384615 30.0 0.107051282051 468 | 157 0.06830078125 30.1910828025 28.0 0.0782529572338 469 | 158 0.06830078125 28.1772151899 27.0 0.0436005625879 470 | 159 0.06830078125 27.1698113208 27.0 0.0062893081761 471 | 160 0.06830078125 27.16875 27.0 0.00625 472 | 161 0.06830078125 27.1677018634 26.0 0.044911610129 473 | 162 0.06830078125 26.1604938272 27.0 0.0310928212163 474 | 163 0.06830078125 27.1656441718 27.0 0.00613496932515 475 | 164 0.06830078125 27.1646341463 29.0 0.0632884777124 476 | 165 0.06830078125 29.1757575758 32.0 0.0882575757576 477 | 166 0.06830078125 32.1927710843 34.0 0.0531537916371 478 | 167 0.06830078125 34.2035928144 35.0 0.022754491018 479 | 168 0.06830078125 35.2083333333 37.0 0.0484234234234 480 | 169 0.06830078125 37.2189349112 38.0 0.020554344441 481 | 170 0.06830078125 38.2235294118 39.0 0.0199095022624 482 | 171 0.06830078125 39.2280701754 42.0 0.0659983291562 483 | 172 0.06830078125 42.2441860465 41.0 0.0303460011344 484 | 173 0.06830078125 41.2369942197 39.0 0.057358826145 485 | 174 0.06830078125 39.224137931 39.0 0.00574712643678 486 | 175 0.06830078125 39.2228571429 39.0 0.00571428571429 487 | 176 0.06830078125 39.2215909091 41.0 0.0433758314856 488 | 177 0.06830078125 41.2316384181 41.0 0.00564971751412 489 | 178 0.06830078125 41.2303370787 39.0 0.0571881302218 490 | 179 0.06830078125 39.217877095 34.0 0.153466973382 491 | 180 0.06830078125 34.1888888889 30.0 0.13962962963 492 | 181 0.06830078125 30.1657458564 28.0 0.0773480662983 493 | 182 0.06830078125 28.1538461538 28.0 0.00549450549451 494 | 183 0.06830078125 28.1530054645 28.0 0.00546448087432 495 | 184 0.06830078125 28.152173913 27.0 0.0426731078905 496 | 185 0.06830078125 27.1459459459 27.0 0.00540540540541 497 | 186 0.06830078125 27.1451612903 27.0 0.00537634408602 498 | 187 0.06830078125 27.1443850267 28.0 0.0305576776165 499 | 188 0.06830078125 28.1489361702 29.0 0.0293470286134 500 | 189 0.06830078125 29.1534391534 33.0 0.116562449896 501 | 190 0.06830078125 33.1736842105 35.0 0.0521804511278 502 | 191 0.06830078125 35.1832460733 36.0 0.022687609075 503 | 192 0.06830078125 36.1875 38.0 0.0476973684211 504 | 193 0.06830078125 38.1968911917 39.0 0.0205925335459 505 | 194 0.06830078125 39.2010309278 40.0 0.0199742268041 506 | 195 0.06830078125 40.2051282051 43.0 0.0649970184854 507 | 196 0.06830078125 43.2193877551 41.0 0.054131408661 508 | 197 0.06830078125 41.2081218274 40.0 0.0302030456853 509 | 198 0.06830078125 40.202020202 40.0 0.00505050505051 510 | 199 0.06830078125 40.2010050251 40.0 0.00502512562814 511 | 200 0.06830078125 40.2 41.0 0.019512195122 512 | 201 0.06830078125 41.2039800995 41.0 0.00497512437811 513 | 202 0.06830078125 41.202970297 39.0 0.0564864178726 514 | 203 0.06830078125 39.1921182266 33.0 0.187639946261 515 | 204 0.06830078125 33.1617647059 30.0 0.105392156863 516 | 205 0.06830078125 30.1463414634 27.0 0.116531165312 517 | 206 0.06830078125 27.1310679612 27.0 0.00485436893204 518 | 207 0.06830078125 27.1304347826 27.0 0.0048309178744 519 | 208 0.06830078125 27.1298076923 27.0 0.00480769230769 520 | 209 0.06830078125 27.1291866029 27.0 0.00478468899522 521 | 210 0.06830078125 27.1285714286 28.0 0.0311224489796 522 | 211 0.06830078125 28.1327014218 28.0 0.00473933649289 523 | 212 0.06830078125 28.1320754717 30.0 0.0622641509434 524 | 213 0.06830078125 30.1408450704 34.0 0.113504556752 525 | 214 0.06830078125 34.1588785047 35.0 0.0240320427236 526 | 215 0.06830078125 35.1627906977 36.0 0.0232558139535 527 | 216 0.06830078125 36.1666666667 36.0 0.00462962962963 528 | 217 0.06830078125 36.1658986175 38.0 0.048265825855 529 | 218 0.06830078125 38.1743119266 39.0 0.0211714890614 530 | 219 0.06830078125 39.1780821918 42.0 0.0671885192433 531 | 220 0.06830078125 42.1909090909 40.0 0.0547727272727 532 | 221 0.06830078125 40.1809954751 39.0 0.0302819352593 533 | 222 0.06830078125 39.1756756757 39.0 0.0045045045045 534 | 223 0.06830078125 39.1748878924 39.0 0.00448430493274 535 | 224 0.06830078125 39.1741071429 40.0 0.0206473214286 536 | 225 0.06830078125 40.1777777778 40.0 0.00444444444444 537 | 226 0.06830078125 40.1769911504 38.0 0.0572892408011 538 | 227 0.06830078125 38.1674008811 34.0 0.122570614149 539 | 228 0.06830078125 34.149122807 30.0 0.138304093567 540 | 229 0.06830078125 30.1310043668 28.0 0.0761072988147 541 | 230 0.06830078125 28.1217391304 27.0 0.0415458937198 542 | 231 0.06830078125 27.1168831169 27.0 0.004329004329 543 | 232 0.06830078125 27.1163793103 28.0 0.0315578817734 544 | 233 0.06830078125 28.1201716738 27.0 0.0414878397711 545 | 234 0.06830078125 27.1153846154 27.0 0.0042735042735 546 | 235 0.06830078125 27.114893617 27.0 0.00425531914894 547 | 236 0.06830078125 27.1144067797 29.0 0.0650204558738 548 | 237 0.06830078125 29.1223628692 33.0 0.117504155479 549 | 238 0.06830078125 33.1386554622 34.0 0.0253336628769 550 | 239 0.06830078125 34.1422594142 35.0 0.0245068738793 551 | 240 0.06830078125 35.1458333333 37.0 0.0501126126126 552 | 241 0.06830078125 37.153526971 38.0 0.0222756060275 553 | 242 0.06830078125 38.1570247934 39.0 0.0216147488875 554 | 243 0.06830078125 39.1604938272 42.0 0.0676072898295 555 | 244 0.06830078125 42.1721311475 40.0 0.0543032786885 556 | 245 0.06830078125 40.1632653061 39.0 0.0298273155416 557 | 246 0.06830078125 39.1585365854 38.0 0.030487804878 558 | 247 0.06830078125 38.1538461538 38.0 0.00404858299595 559 | 248 0.06830078125 38.1532258065 40.0 0.0461693548387 560 | 249 0.06830078125 40.1606425703 40.0 0.00401606425703 561 | 250 0.06830078125 40.16 38.0 0.0568421052632 562 | 251 0.06830078125 38.1513944223 33.0 0.156102861282 563 | 252 0.06830078125 33.130952381 30.0 0.104365079365 564 | 253 0.06830078125 30.1185770751 28.0 0.0756634669678 565 | 254 0.06830078125 28.1102362205 27.0 0.0411198600175 566 | 255 0.06830078125 27.1058823529 27.0 0.00392156862745 567 | 256 0.06830078125 27.10546875 28.0 0.0319475446429 568 | 257 0.06830078125 28.1089494163 27.0 0.0410722006053 569 | 258 0.06830078125 27.1046511628 27.0 0.00387596899225 570 | 259 0.06830078125 27.1042471042 28.0 0.0319911748483 571 | 260 0.06830078125 28.1076923077 29.0 0.0307692307692 572 | 261 0.06830078125 29.1111111111 33.0 0.117845117845 573 | 262 0.06830078125 33.1259541985 35.0 0.0535441657579 574 | 263 0.06830078125 35.1330798479 36.0 0.0240811153359 575 | 264 0.06830078125 36.1363636364 36.0 0.00378787878788 576 | 265 0.06830078125 36.1358490566 37.0 0.0233554309026 577 | 266 0.06830078125 37.1390977444 37.0 0.00375939849624 578 | 267 0.06830078125 37.138576779 41.0 0.0941810541701 579 | 268 0.06830078125 41.1529850746 39.0 0.0552047455033 580 | 269 0.06830078125 39.1449814126 38.0 0.0301310898063 581 | 270 0.06830078125 38.1407407407 38.0 0.0037037037037 582 | 271 0.06830078125 38.1402214022 37.0 0.0308167946544 583 | 272 0.06830078125 37.1360294118 39.0 0.0477941176471 584 | 273 0.06830078125 39.1428571429 40.0 0.0214285714286 585 | 274 0.06830078125 40.1459854015 37.0 0.0850266324719 586 | 275 0.06830078125 37.1345454545 33.0 0.125289256198 587 | 276 0.06830078125 33.1195652174 29.0 0.142053973013 588 | 277 0.06830078125 29.1046931408 27.0 0.0779515978072 589 | 278 0.06830078125 27.0971223022 27.0 0.00359712230216 590 | 279 0.06830078125 27.0967741935 27.0 0.00358422939068 591 | 280 0.06830078125 27.0964285714 28.0 0.0322704081633 592 | 281 0.06830078125 28.0996441281 27.0 0.0407275603005 593 | 282 0.06830078125 27.0957446809 28.0 0.0322948328267 594 | 283 0.06830078125 28.0989399293 28.0 0.00353356890459 595 | 284 0.06830078125 28.0985915493 29.0 0.0310830500243 596 | 285 0.06830078125 29.101754386 32.0 0.0905701754386 597 | 286 0.06830078125 32.1118881119 34.0 0.0555327025915 598 | 287 0.06830078125 34.118466899 34.0 0.00348432055749 599 | 288 0.06830078125 34.1180555556 35.0 0.0251984126984 600 | 289 0.06830078125 35.1211072664 36.0 0.0244136870434 601 | 290 0.06830078125 36.124137931 37.0 0.0236719478099 602 | 291 0.06830078125 37.1271477663 40.0 0.0718213058419 603 | 292 0.06830078125 40.1369863014 39.0 0.0291534949069 604 | 293 0.06830078125 39.133105802 37.0 0.0576515081635 605 | 294 0.06830078125 37.1258503401 37.0 0.00340136054422 606 | 295 0.06830078125 37.1254237288 37.0 0.00338983050847 607 | 296 0.06830078125 37.125 39.0 0.0480769230769 608 | 297 0.06830078125 39.1313131313 39.0 0.003367003367 609 | 298 0.06830078125 39.1308724832 37.0 0.0575911481952 610 | 299 0.06830078125 37.1237458194 33.0 0.124961994527 611 | 300 0.06830078125 33.11 29.0 0.141724137931 612 | 301 0.06830078125 29.096345515 27.0 0.0776424264796 613 | 302 0.06830078125 27.0894039735 26.0 0.0419001528273 614 | 303 0.06830078125 26.0858085809 27.0 0.0338589414497 615 | 304 0.06830078125 27.0888157895 27.0 0.00328947368421 616 | 305 0.06830078125 27.0885245902 27.0 0.00327868852459 617 | 306 0.06830078125 27.0882352941 28.0 0.0325630252101 618 | 307 0.06830078125 28.0912052117 28.0 0.00325732899023 619 | 308 0.06830078125 28.0909090909 29.0 0.0313479623824 620 | 309 0.06830078125 29.0938511327 32.0 0.0908171521036 621 | 310 0.06830078125 32.1032258065 33.0 0.0271749755621 622 | 311 0.06830078125 33.1061093248 34.0 0.026290902213 623 | 1 0.06830078125 82.0 41.0 41.0 624 | 2 0.06830078125 61.5 42.0 9.05357142857 625 | 3 0.06830078125 56.0 46.0 2.17391304348 626 | 4 0.06830078125 57.5 43.0 4.88953488372 627 | 5 0.06830078125 51.6 42.0 2.19428571429 628 | 6 0.06830078125 49.0 42.0 1.16666666667 629 | 7 0.06830078125 48.0 42.0 0.857142857143 630 | 8 0.06830078125 47.25 44.0 0.240056818182 631 | 9 0.06830078125 48.8888888889 44.0 0.543209876543 632 | 10 0.06830078125 48.4 42.0 0.975238095238 633 | 11 0.06830078125 45.8181818182 38.0 1.60852544585 634 | 12 0.06830078125 41.1666666667 35.0 1.08650793651 635 | 13 0.06830078125 37.6923076923 33.0 0.667204590282 636 | 14 0.06830078125 35.3571428571 33.0 0.168367346939 637 | 15 0.06830078125 35.2 33.0 0.146666666667 638 | 16 0.06830078125 35.0625 32.0 0.293090820313 639 | 17 0.06830078125 33.8823529412 32.0 0.110726643599 640 | 18 0.06830078125 33.7777777778 33.0 0.0183314627759 641 | 19 0.06830078125 34.7368421053 34.0 0.0159687143555 642 | 20 0.06830078125 35.7 35.0 0.014 643 | 21 0.06830078125 36.6666666667 38.0 0.046783625731 644 | 22 0.06830078125 39.7272727273 39.0 0.0135621953804 645 | 23 0.06830078125 40.6956521739 39.0 0.0737240075614 646 | 24 0.06830078125 40.625 41.0 0.00342987804878 647 | 25 0.06830078125 42.64 42.0 0.00975238095238 648 | 26 0.06830078125 43.6153846154 42.0 0.0621301775148 649 | 27 0.06830078125 43.5555555556 46.0 0.129898013956 650 | 28 0.06830078125 47.6428571429 44.0 0.301600185529 651 | 29 0.06830078125 45.5172413793 43.0 0.1473605619 652 | 30 0.06830078125 44.4333333333 43.0 0.0477777777778 653 | 31 0.06830078125 44.3870967742 43.0 0.044745057232 654 | 32 0.06830078125 44.34375 44.0 0.002685546875 655 | 33 0.06830078125 45.3333333333 44.0 0.040404040404 656 | 34 0.06830078125 45.2941176471 42.0 0.258362168397 657 | 35 0.06830078125 43.2 38.0 0.711578947368 658 | 36 0.06830078125 39.0555555556 34.0 0.75172476398 659 | 37 0.06830078125 34.9189189189 32.0 0.266252739226 660 | 38 0.06830078125 32.8421052632 32.0 0.0221606648199 661 | 39 0.06830078125 32.8205128205 32.0 0.0210387902696 662 | 40 0.06830078125 32.8 32.0 0.02 663 | 41 0.06830078125 32.7804878049 32.0 0.0190362879239 664 | 42 0.06830078125 32.7619047619 34.0 0.0450847005469 665 | 43 0.06830078125 34.7906976744 34.0 0.0183883180097 666 | 44 0.06830078125 34.7727272727 35.0 0.00147579693034 667 | 45 0.06830078125 35.7777777778 38.0 0.129954515919 668 | 46 0.06830078125 38.8260869565 39.0 0.000775531966458 669 | 47 0.06830078125 39.829787234 40.0 0.000724309642372 670 | 48 0.06830078125 40.8333333333 40.0 0.0173611111111 671 | 49 0.06830078125 40.8163265306 41.0 0.000822827886755 672 | 50 0.06830078125 41.82 41.0 0.0164 673 | 51 0.06830078125 41.8039215686 45.0 0.2269981631 674 | 52 0.06830078125 45.8653846154 43.0 0.190940209165 675 | 53 0.06830078125 43.8113207547 41.0 0.192768887461 676 | 54 0.06830078125 41.7592592593 41.0 0.0140603566529 677 | 55 0.06830078125 41.7454545455 41.0 0.0135537190083 678 | 56 0.06830078125 41.7321428571 43.0 0.0373828310394 679 | 57 0.06830078125 43.7543859649 43.0 0.0132348414897 680 | 58 0.06830078125 43.7413793103 40.0 0.349947978597 681 | 59 0.06830078125 40.6779661017 36.0 0.60787130135 682 | 60 0.06830078125 36.6 33.0 0.392727272727 683 | 61 0.06830078125 33.5409836066 31.0 0.2082773448 684 | 62 0.06830078125 31.5 31.0 0.00806451612903 685 | 63 0.06830078125 31.4920634921 31.0 0.00781053162006 686 | 64 0.06830078125 31.484375 31.0 0.007568359375 687 | 65 0.06830078125 31.4769230769 32.0 0.00855029585799 688 | 66 0.06830078125 32.4848484848 33.0 0.00804185101706 689 | 67 0.06830078125 33.4925373134 33.0 0.00735130318556 690 | 68 0.06830078125 33.4852941176 34.0 0.00779182780379 691 | 69 0.06830078125 34.4927536232 37.0 0.169899578217 692 | 70 0.06830078125 37.5285714286 39.0 0.055515436944 693 | 71 0.06830078125 39.5492957746 39.0 0.00773656020631 694 | 72 0.06830078125 39.5416666667 39.0 0.00752314814815 695 | 73 0.06830078125 39.5342465753 39.0 0.00731844623757 696 | 74 0.06830078125 39.527027027 39.0 0.00712198685172 697 | 75 0.06830078125 39.52 43.0 0.281637209302 698 | 76 0.06830078125 43.5657894737 41.0 0.160567698129 699 | 77 0.06830078125 41.5324675325 40.0 0.0587114184517 700 | 78 0.06830078125 40.5128205128 40.0 0.00657462195924 701 | 79 0.06830078125 40.5063291139 40.0 0.00640922929018 702 | 80 0.06830078125 40.5 41.0 0.00609756097561 703 | 81 0.06830078125 41.5061728395 41.0 0.00624904740131 704 | 82 0.06830078125 41.5 39.0 0.160256410256 705 | 83 0.06830078125 39.4698795181 35.0 0.570852083031 706 | 84 0.06830078125 35.4166666667 32.0 0.364800347222 707 | 85 0.06830078125 32.3764705882 30.0 0.188253748558 708 | 86 0.06830078125 30.3488372093 29.0 0.0627366143862 709 | 87 0.06830078125 29.3333333333 29.0 0.00383141762452 710 | 88 0.06830078125 29.3295454545 31.0 0.090013496401 711 | 89 0.06830078125 31.3483146067 31.0 0.00391364726676 712 | 90 0.06830078125 31.3444444444 32.0 0.0134297839506 713 | 91 0.06830078125 32.3516483516 32.0 0.00386426760053 714 | 92 0.06830078125 32.347826087 34.0 0.0802846658512 715 | 93 0.06830078125 34.3655913978 37.0 0.187570504948 716 | 94 0.06830078125 37.3936170213 38.0 0.00967632412856 717 | 95 0.06830078125 38.4 38.0 0.00421052631579 718 | 96 0.06830078125 38.3958333333 38.0 0.00412326388889 719 | 97 0.06830078125 38.3917525773 38.0 0.00403868636412 720 | 98 0.06830078125 38.387755102 38.0 0.0039566847147 721 | 99 0.06830078125 38.3838383838 42.0 0.311348210338 722 | 100 0.06830078125 42.42 40.0 0.14641 723 | 101 0.06830078125 40.396039604 39.0 0.0499724763032 724 | 102 0.06830078125 39.3823529412 39.0 0.00374855824683 725 | 103 0.06830078125 39.3786407767 39.0 0.00367612404562 726 | 104 0.06830078125 39.375 41.0 0.0644054878049 727 | 105 0.06830078125 41.3904761905 41.0 0.00371882086168 728 | 106 0.06830078125 41.3867924528 38.0 0.301851661014 729 | 107 0.06830078125 38.3551401869 35.0 0.321627590682 730 | 108 0.06830078125 35.3240740741 31.0 0.603148922519 731 | 109 0.06830078125 31.2844036697 29.0 0.179948280216 732 | 110 0.06830078125 29.2636363636 29.0 0.00239669421488 733 | 111 0.06830078125 29.2612612613 29.0 0.00235370505641 734 | 112 0.06830078125 29.2589285714 29.0 0.0023118622449 735 | 113 0.06830078125 29.2566371681 30.0 0.018419609993 736 | 114 0.06830078125 30.2631578947 31.0 0.0175140738093 737 | 115 0.06830078125 31.2695652174 31.0 0.00234404536862 738 | 116 0.06830078125 31.2672413793 32.0 0.0167792248811 739 | 117 0.06830078125 32.2735042735 35.0 0.212393684189 740 | 118 0.06830078125 35.2966101695 36.0 0.0137432570462 741 | 119 0.06830078125 36.3025210084 37.0 0.0131480255059 742 | 120 0.06830078125 37.3083333333 36.0 0.0475482253086 743 | 121 0.06830078125 36.2975206612 37.0 0.0133372222027 744 | 122 0.06830078125 37.3032786885 37.0 0.00248589088955 745 | 123 0.06830078125 37.3008130081 41.0 0.333755717093 746 | 124 0.06830078125 41.3306451613 38.0 0.291926241853 747 | 125 0.06830078125 38.304 37.0 0.0459571891892 748 | 126 0.06830078125 37.2936507937 37.0 0.00233056185437 749 | 127 0.06830078125 37.2913385827 37.0 0.00229400458801 750 | 128 0.06830078125 37.2890625 39.0 0.0750591571514 751 | 129 0.06830078125 39.3023255814 39.0 0.0023436091581 752 | 130 0.06830078125 39.3 37.0 0.142972972973 753 | 131 0.06830078125 37.2824427481 33.0 0.555736845172 754 | 132 0.06830078125 33.25 30.0 0.352083333333 755 | 133 0.06830078125 30.2255639098 28.0 0.176897668446 756 | 134 0.06830078125 28.2089552239 27.0 0.0541323234573 757 | 135 0.06830078125 27.2 27.0 0.00148148148148 758 | 136 0.06830078125 27.1985294118 27.0 0.00145977508651 759 | 137 0.06830078125 27.197080292 30.0 0.261878629655 760 | 138 0.06830078125 30.2173913043 31.0 0.0197573022745 761 | 139 0.06830078125 31.2230215827 31.0 0.00160447181823 762 | 140 0.06830078125 31.2214285714 31.0 0.00158163265306 763 | 141 0.06830078125 31.219858156 34.0 0.227329078606 764 | 142 0.06830078125 34.2394366197 35.0 0.0165273330122 765 | 143 0.06830078125 35.2447552448 35.0 0.00171157513815 766 | 144 0.06830078125 35.2430555556 36.0 0.0159156914438 767 | 145 0.06830078125 36.2482758621 37.0 0.0152726805283 768 | 146 0.06830078125 37.2534246575 38.0 0.0146677563678 769 | 147 0.06830078125 38.2585034014 41.0 0.183312282935 770 | 148 0.06830078125 41.277027027 39.0 0.132944925175 771 | 149 0.06830078125 39.2617449664 38.0 0.0418947463248 772 | 150 0.06830078125 38.2533333333 38.0 0.00168888888889 773 | 151 0.06830078125 38.2516556291 38.0 0.00166659357046 774 | 152 0.06830078125 38.25 40.0 0.0765625 775 | 153 0.06830078125 40.2614379085 40.0 0.00170874449998 776 | 154 0.06830078125 40.2597402597 38.0 0.134379632671 777 | 155 0.06830078125 38.2451612903 33.0 0.833688392773 778 | 156 0.06830078125 33.2115384615 30.0 0.343799309665 779 | 157 0.06830078125 30.1910828025 28.0 0.171458708844 780 | 158 0.06830078125 28.1772151899 27.0 0.0513272445655 781 | 159 0.06830078125 27.1698113208 27.0 0.00106799572802 782 | 160 0.06830078125 27.16875 27.0 0.0010546875 783 | 161 0.06830078125 27.1677018634 26.0 0.0524433708339 784 | 162 0.06830078125 26.1604938272 27.0 0.0261026153421 785 | 163 0.06830078125 27.1656441718 27.0 0.00101622191276 786 | 164 0.06830078125 27.1646341463 29.0 0.116157510923 787 | 165 0.06830078125 29.1757575758 32.0 0.249260789715 788 | 166 0.06830078125 32.1927710843 34.0 0.0960610692237 789 | 167 0.06830078125 34.2035928144 35.0 0.018121840152 790 | 168 0.06830078125 35.2083333333 37.0 0.0867586336336 791 | 169 0.06830078125 37.2189349112 38.0 0.0160542808651 792 | 170 0.06830078125 38.2235294118 39.0 0.0154591429332 793 | 171 0.06830078125 39.2280701754 42.0 0.182942736959 794 | 172 0.06830078125 42.2441860465 41.0 0.0377560711789 795 | 173 0.06830078125 41.2369942197 39.0 0.128311362532 796 | 174 0.06830078125 39.224137931 39.0 0.00128814902893 797 | 175 0.06830078125 39.2228571429 39.0 0.00127346938776 798 | 176 0.06830078125 39.2215909091 41.0 0.0771399730397 799 | 177 0.06830078125 41.2316384181 41.0 0.00130869162757 800 | 178 0.06830078125 41.2303370787 39.0 0.127548807293 801 | 179 0.06830078125 39.217877095 34.0 0.800771805242 802 | 180 0.06830078125 34.1888888889 30.0 0.584893004115 803 | 181 0.06830078125 30.1657458564 28.0 0.167516254083 804 | 182 0.06830078125 28.1538461538 28.0 0.000845308537616 805 | 183 0.06830078125 28.1530054645 28.0 0.000836095434322 806 | 184 0.06830078125 28.152173913 27.0 0.0491668416999 807 | 185 0.06830078125 27.1459459459 27.0 0.000788897005113 808 | 186 0.06830078125 27.1451612903 27.0 0.000780437044745 809 | 187 0.06830078125 27.1443850267 28.0 0.0261456065168 810 | 188 0.06830078125 28.1489361702 29.0 0.0249761945646 811 | 189 0.06830078125 29.1534391534 33.0 0.448364555948 812 | 190 0.06830078125 33.1736842105 35.0 0.0952979817966 813 | 191 0.06830078125 35.1832460733 36.0 0.0185301937995 814 | 192 0.06830078125 36.1875 38.0 0.0864514802632 815 | 193 0.06830078125 38.1968911917 39.0 0.0165380450757 816 | 194 0.06830078125 39.2010309278 40.0 0.0159587894569 817 | 195 0.06830078125 40.2051282051 43.0 0.181658333716 818 | 196 0.06830078125 43.2193877551 41.0 0.120138585549 819 | 197 0.06830078125 41.2081218274 40.0 0.0364889587467 820 | 198 0.06830078125 40.202020202 40.0 0.00102030405061 821 | 199 0.06830078125 40.2010050251 40.0 0.00101007550314 822 | 200 0.06830078125 40.2 41.0 0.0156097560976 823 | 201 0.06830078125 41.2039800995 41.0 0.00101482636568 824 | 202 0.06830078125 41.202970297 39.0 0.124437900759 825 | 203 0.06830078125 39.1921182266 33.0 1.16188873128 826 | 204 0.06830078125 33.1617647059 30.0 0.333225201845 827 | 205 0.06830078125 30.1463414634 27.0 0.3666468372 828 | 206 0.06830078125 27.1310679612 27.0 0.000636252238665 829 | 207 0.06830078125 27.1304347826 27.0 0.000630119722747 830 | 208 0.06830078125 27.1298076923 27.0 0.000624075443787 831 | 209 0.06830078125 27.1291866029 27.0 0.000618117717085 832 | 210 0.06830078125 27.1285714286 28.0 0.0271209912536 833 | 211 0.06830078125 28.1327014218 28.0 0.000628916691 834 | 212 0.06830078125 28.1320754717 30.0 0.116304734781 835 | 213 0.06830078125 30.1408450704 34.0 0.43803166972 836 | 214 0.06830078125 34.1588785047 35.0 0.0202138677115 837 | 215 0.06830078125 35.1627906977 36.0 0.019469983775 838 | 216 0.06830078125 36.1666666667 36.0 0.000771604938272 839 | 217 0.06830078125 36.1658986175 38.0 0.0885244179275 840 | 218 0.06830078125 38.1743119266 39.0 0.017481046014 841 | 219 0.06830078125 39.1780821918 42.0 0.189600478961 842 | 220 0.06830078125 42.1909090909 40.0 0.120002066116 843 | 221 0.06830078125 40.1809954751 39.0 0.0357628285189 844 | 222 0.06830078125 39.1756756757 39.0 0.000791331872413 845 | 223 0.06830078125 39.1748878924 39.0 0.00078425063846 846 | 224 0.06830078125 39.1741071429 40.0 0.017052475287 847 | 225 0.06830078125 40.1777777778 40.0 0.00079012345679 848 | 226 0.06830078125 40.1769911504 38.0 0.12471817024 849 | 227 0.06830078125 38.1674008811 34.0 0.510800885395 850 | 228 0.06830078125 34.149122807 30.0 0.573840668924 851 | 229 0.06830078125 30.1310043668 28.0 0.16218498612 852 | 230 0.06830078125 28.1217391304 27.0 0.0466036546944 853 | 231 0.06830078125 27.1168831169 27.0 0.000505987518974 854 | 232 0.06830078125 27.1163793103 28.0 0.0278851972567 855 | 233 0.06830078125 28.1201716738 27.0 0.0464735029196 856 | 234 0.06830078125 27.1153846154 27.0 0.000493096646943 857 | 235 0.06830078125 27.114893617 27.0 0.000488909008601 858 | 236 0.06830078125 27.1144067797 29.0 0.122602130779 859 | 237 0.06830078125 29.1223628692 33.0 0.455638476308 860 | 238 0.06830078125 33.1386554622 34.0 0.0218210121419 861 | 239 0.06830078125 34.1422594142 35.0 0.0210205403567 862 | 240 0.06830078125 35.1458333333 37.0 0.0929171358859 863 | 241 0.06830078125 37.153526971 38.0 0.0188556997079 864 | 242 0.06830078125 38.1570247934 39.0 0.0182206974093 865 | 243 0.06830078125 39.1604938272 42.0 0.1919713168 866 | 244 0.06830078125 42.1721311475 40.0 0.117953843053 867 | 245 0.06830078125 40.1632653061 39.0 0.0346970813443 868 | 246 0.06830078125 39.1585365854 38.0 0.0353212373587 869 | 247 0.06830078125 38.1538461538 38.0 0.000622858922454 870 | 248 0.06830078125 38.1532258065 40.0 0.0852643730489 871 | 249 0.06830078125 40.1606425703 40.0 0.000645150884663 872 | 250 0.06830078125 40.16 38.0 0.122778947368 873 | 251 0.06830078125 38.1513944223 33.0 0.804147408916 874 | 252 0.06830078125 33.130952381 30.0 0.326762093726 875 | 253 0.06830078125 30.1185770751 28.0 0.160298886541 876 | 254 0.06830078125 28.1102362205 27.0 0.0456527579722 877 | 255 0.06830078125 27.1058823529 27.0 0.000415224913495 878 | 256 0.06830078125 27.10546875 28.0 0.0285780770438 879 | 257 0.06830078125 28.1089494163 27.0 0.0455469928891 880 | 258 0.06830078125 27.1046511628 27.0 0.000405624661979 881 | 259 0.06830078125 27.1042471042 28.0 0.0286561875089 882 | 260 0.06830078125 28.1076923077 29.0 0.0274556213018 883 | 261 0.06830078125 29.1111111111 33.0 0.458286569398 884 | 262 0.06830078125 33.1259541985 35.0 0.100344219035 885 | 263 0.06830078125 35.1330798479 36.0 0.0208764041695 886 | 264 0.06830078125 36.1363636364 36.0 0.00051652892562 887 | 265 0.06830078125 36.1358490566 37.0 0.0201826176479 888 | 266 0.06830078125 37.1390977444 37.0 0.000522923850981 889 | 267 0.06830078125 37.138576779 41.0 0.363672909548 890 | 268 0.06830078125 41.1529850746 39.0 0.118854993117 891 | 269 0.06830078125 39.1449814126 38.0 0.0344995377708 892 | 270 0.06830078125 38.1407407407 38.0 0.000521262002744 893 | 271 0.06830078125 38.1402214022 37.0 0.0351379688126 894 | 272 0.06830078125 37.1360294118 39.0 0.0890868295848 895 | 273 0.06830078125 39.1428571429 40.0 0.0183673469388 896 | 274 0.06830078125 40.1459854015 37.0 0.267492544492 897 | 275 0.06830078125 37.1345454545 33.0 0.518014124718 898 | 276 0.06830078125 33.1195652174 29.0 0.585200606219 899 | 277 0.06830078125 29.1046931408 27.0 0.164064193219 900 | 278 0.06830078125 27.0971223022 27.0 0.00034936079913 901 | 279 0.06830078125 27.0967741935 27.0 0.000346860908776 902 | 280 0.06830078125 27.0964285714 28.0 0.0291586188047 903 | 281 0.06830078125 28.0996441281 27.0 0.0447858225369 904 | 282 0.06830078125 27.0957446809 28.0 0.0292027743646 905 | 283 0.06830078125 28.0989399293 28.0 0.000349611057698 906 | 284 0.06830078125 28.0985915493 29.0 0.0280185239656 907 | 285 0.06830078125 29.101754386 32.0 0.262494613727 908 | 286 0.06830078125 32.1118881119 34.0 0.104851955942 909 | 287 0.06830078125 34.118466899 34.0 0.00041277665141 910 | 288 0.06830078125 34.1180555556 35.0 0.0222236000882 911 | 289 0.06830078125 35.1211072664 36.0 0.021457012142 912 | 290 0.06830078125 36.124137931 37.0 0.0207333611852 913 | 291 0.06830078125 37.1271477663 40.0 0.206331998914 914 | 292 0.06830078125 40.1369863014 39.0 0.0331471243462 915 | 293 0.06830078125 39.133105802 37.0 0.12297676656 916 | 294 0.06830078125 37.1258503401 37.0 0.000428062381415 917 | 295 0.06830078125 37.1254237288 37.0 0.000425165182419 918 | 296 0.06830078125 37.125 39.0 0.0901442307692 919 | 297 0.06830078125 39.1313131313 39.0 0.000442131755263 920 | 298 0.06830078125 39.1308724832 37.0 0.122719392966 921 | 299 0.06830078125 37.1237458194 33.0 0.515311502515 922 | 300 0.06830078125 33.11 29.0 0.582486206897 923 | 301 0.06830078125 29.096345515 27.0 0.16276535252 924 | 302 0.06830078125 27.0894039735 26.0 0.0456461929807 925 | 303 0.06830078125 26.0858085809 27.0 0.0309535537345 926 | 304 0.06830078125 27.0888157895 27.0 0.000292157202216 927 | 305 0.06830078125 27.0885245902 27.0 0.000290244557915 928 | 306 0.06830078125 27.0882352941 28.0 0.0296898171033 929 | 307 0.06830078125 28.0912052117 28.0 0.000297085380216 930 | 308 0.06830078125 28.0909090909 29.0 0.0284981476204 931 | 309 0.06830078125 29.0938511327 32.0 0.263928163718 932 | 310 0.06830078125 32.1032258065 33.0 0.0243698167944 933 | 311 0.06830078125 33.1061093248 34.0 0.0235011923319 934 | -------------------------------------------------------------------------------- /machinelearning/getAirElement.py: -------------------------------------------------------------------------------- 1 | import pycurl 2 | import json 3 | import sqlite3 4 | from io import BytesIO 5 | 6 | buffer = BytesIO() 7 | 8 | mycurl = pycurl.Curl() 9 | mycurl.setopt(pycurl.URL, 'http://www.pm25.in/api/querys/all_cities.json') 10 | mycurl.setopt(pycurl.WRITEDATA, buffer) 11 | try: 12 | mycurl.perform() 13 | except Exception as e: 14 | print(Exception, ":", e) 15 | print("") 16 | mycurl.close() 17 | 18 | print("mycurl.perform() over") 19 | 20 | body = buffer.getvalue() 21 | with open("data.dat", "w") as f: 22 | print(body, file=f) 23 | 24 | print(body) 25 | -------------------------------------------------------------------------------- /sensor/arduino/README.md: -------------------------------------------------------------------------------- 1 | # ThingSpeak平台: 2 | https://cn.mathworks.com/help/thingspeak/get-a-channel-feed.html 3 | ================================================================== 4 | ### 读取例子: 5 | https://api.thingspeak.com/channels/205195.json 6 | https://api.thingspeak.com/channels/205195/feeds.json?results=2 7 | https://api.thingspeak.com/channels/205195/feeds.json?start=2016-12-20%2010:36:17&end=2016-12-20%2021:06:46 8 | https://api.thingspeak.com/channels/205195/feeds/last.json 9 | -------------------------------------------------------------------------------- /sensor/arduino/sensor/sensor.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define pm25_RX 10 4 | #define pm25_TX 11 5 | #define CO A0 6 | #define SO2 A1 7 | #define O3 A2 8 | #define HCHO A3 9 | #define MQ2 A4 10 | 11 | SoftwareSerial mySerial_pm(pm25_RX, pm25_TX); 12 | float A = 800.0; 13 | 14 | float value_pm25 = 0.0; 15 | float value_CO = 0.0; 16 | float value_SO2 = 0.0; 17 | float value_O3 = 0.0; 18 | float value_HCHO = 0.0; 19 | float value_MQ2 = 0.0; 20 | 21 | void setup() { 22 | // put your setup code here, to run once: 23 | Serial.begin(9600); 24 | mySerial_pm.begin(2400); 25 | pinMode(CO, INPUT); 26 | pinMode(SO2, INPUT); 27 | pinMode(O3, INPUT); 28 | pinMode(HCHO, INPUT); 29 | pinMode(MQ2, INPUT); 30 | } 31 | 32 | void loop() { 33 | // put your main code here, to run repeatedly: 34 | //Serial.println("start"); 35 | int temp; 36 | temp = read_pm(pm25_RX, pm25_TX); 37 | if (temp > 0) { 38 | value_pm25 = temp; 39 | } 40 | Serial.print("PM2.5:"); Serial.println(value_pm25); 41 | 42 | value_CO = map(analogRead(CO), 0, 1023, 0, 1000); 43 | Serial.print("CO:"); Serial.println(value_CO); 44 | 45 | value_SO2 = map(analogRead(SO2), 0, 1023, 0, 500); 46 | Serial.print("SO2:"); Serial.println(value_SO2); 47 | 48 | value_O3 = map(analogRead(O3), 0, 1023, 0, 1000); 49 | Serial.print("O3:"); Serial.println(value_O3); 50 | 51 | value_HCHO = map(analogRead(HCHO), 0, 1023, 0, 1000); 52 | Serial.print("HCHO:"); Serial.println(value_HCHO); 53 | 54 | value_MQ2 = map(analogRead(MQ2), 0, 1023, 0, 1000); 55 | Serial.print("MQ2:"); Serial.println(value_MQ2); 56 | 57 | //Serial.println(""); 58 | //delay(500); 59 | } 60 | 61 | float read_pm(int RX, int TX) { 62 | int Vout_H, Vout_L, Vret_H, Vret_L, check, temp; 63 | float Vout, Ud = 0.0; 64 | 65 | 66 | int count = 0; 67 | int need_read = mySerial_pm.available(); 68 | //Serial.print("need_read : "); Serial.println(need_read); 69 | for (int i = 0; i < need_read; i++) { 70 | temp = mySerial_pm.read(); 71 | if (temp == -1) { 72 | continue; 73 | } 74 | //Serial.print(temp); 75 | if (count == 0) { 76 | if (temp != 170) { 77 | continue; 78 | } 79 | count++; 80 | } 81 | else if (count == 1) { 82 | Vout_H = temp; 83 | count++; 84 | } 85 | else if (count == 2) { 86 | Vout_L = temp; 87 | count++; 88 | } 89 | else if (count == 3) { 90 | Vret_H = temp; 91 | count++; 92 | } 93 | else if (count == 4) { 94 | Vret_L = temp; 95 | count++; 96 | } 97 | else if (count == 5) { 98 | check = temp; 99 | count++; 100 | } 101 | else if (count == 6) { 102 | if (temp == 255) { 103 | if (check == (Vout_H + Vout_L + Vret_H + Vret_L) % 256) { 104 | Vout = (Vout_H * 256 + Vout_L) * 1.0 / 1024 * 8; 105 | Ud = 1.0 * A * Vout; 106 | if (Ud > 0) { 107 | break; 108 | } 109 | else { 110 | count = 0; 111 | } 112 | } 113 | } 114 | } 115 | } 116 | return Ud; 117 | 118 | /* 119 | SoftwareSerial mySerial_pm(RX, TX); 120 | mySerial_pm.begin(2400); 121 | //mySerial_pm.flush(); 122 | //Serial.println("read_pm"); 123 | while (true) { 124 | temp = -1; 125 | while (temp == -1) { 126 | temp = mySerial_pm.read(); 127 | Serial.print(temp); 128 | } 129 | Serial.println(temp); 130 | if (temp == 170) { 131 | //Serial.println(temp); 132 | temp = -1; 133 | while (temp == -1) { 134 | temp = mySerial_pm.read(); 135 | } 136 | Vout_H = temp; 137 | 138 | temp = -1; 139 | while (temp == -1) { 140 | temp = mySerial_pm.read(); 141 | } 142 | Vout_L = temp; 143 | 144 | temp = -1; 145 | while (temp == -1) { 146 | temp = mySerial_pm.read(); 147 | } 148 | Vret_H = temp; 149 | 150 | temp = -1; 151 | while (temp == -1) { 152 | temp = mySerial_pm.read(); 153 | } 154 | Vret_L = temp; 155 | 156 | temp = -1; 157 | while (temp == -1) { 158 | temp = mySerial_pm.read(); 159 | } 160 | check = temp; 161 | 162 | temp = -1; 163 | while (temp == -1) { 164 | temp = mySerial_pm.read(); 165 | } 166 | if (temp == 255) { 167 | //Serial.print(Vout_H);Serial.print(" ");Serial.print(Vout_L);Serial.print(" ");Serial.print(Vret_H);Serial.print(" ");Serial.print(Vret_L);Serial.print(" ");Serial.println(check); 168 | if (check == (Vout_H + Vout_L + Vret_H + Vret_L) % 256) { 169 | Vout = (Vout_H * 256 + Vout_L) * 1.0 / 1024 * 8; 170 | Ud = 1.0 * A * Vout; 171 | //Serial.println(Ud); 172 | if (Ud > 0) { 173 | //Serial.println("Ud>0"); 174 | //Serial.print(Vout_H);Serial.print(" ");Serial.print(Vout_L);Serial.print(" ");Serial.print(Vret_H);Serial.print(" ");Serial.print(Vret_L);Serial.print(" ");Serial.println(check); 175 | break; 176 | } 177 | } 178 | } 179 | temp = -1; 180 | } 181 | } 182 | return Ud; 183 | */ 184 | } 185 | -------------------------------------------------------------------------------- /sensor/arduino/sensor_old/sensor_old.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define LED 12 4 | #define CO A0 5 | 6 | int Vout_H, Vout_L, Vret_H, Vret_L, check, temp; 7 | float Vout, Ud; 8 | 9 | int A = 1000; 10 | 11 | SoftwareSerial mySerial(10, 11); 12 | 13 | void setup() { 14 | // put your setup code here, to run once: 15 | Serial.begin(9600); 16 | mySerial.begin(2400); 17 | pinMode(LED, OUTPUT); 18 | pinMode(CO, INPUT); 19 | } 20 | 21 | void loop() { 22 | // put your main code here, to run repeatedly: 23 | temp = -1; 24 | while (temp == -1) { 25 | temp = mySerial.read(); 26 | } 27 | if (temp == 170) { 28 | temp = -1; 29 | while (temp == -1) { 30 | temp = mySerial.read(); 31 | } 32 | Vout_H = temp; 33 | 34 | temp = -1; 35 | while (temp == -1) { 36 | temp = mySerial.read(); 37 | } 38 | Vout_L = temp; 39 | 40 | temp = -1; 41 | while (temp == -1) { 42 | temp = mySerial.read(); 43 | } 44 | Vret_H = temp; 45 | 46 | temp = -1; 47 | while (temp == -1) { 48 | temp = mySerial.read(); 49 | } 50 | Vret_L = temp; 51 | 52 | temp = -1; 53 | while (temp == -1) { 54 | temp = mySerial.read(); 55 | } 56 | check = temp; 57 | 58 | temp = -1; 59 | while (temp == -1) { 60 | temp = mySerial.read(); 61 | } 62 | if (temp == 255) { 63 | if (check == (Vout_H + Vout_L + Vret_H + Vret_L) % 256) { 64 | Vout = (Vout_H * 256 + Vout_L) * 1.0 / 1024 * 8; 65 | Ud = 1.0 * A * Vout; 66 | if (Ud > 0) { 67 | Serial.print("pm2.5 : "); 68 | Serial.print(Ud); Serial.println("ppm"); 69 | 70 | Serial.print("CO : "); 71 | Serial.print(map(analogRead(CO), 0, 255, 10, 1000)); 72 | Serial.println("ppm"); 73 | 74 | Serial.println(""); 75 | delay(500); 76 | } 77 | } 78 | } 79 | temp = -1; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /sensor/hardware/FWB.ms14: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/sensor/hardware/FWB.ms14 -------------------------------------------------------------------------------- /sensor/raspberrypi/GPIO.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/sensor/raspberrypi/GPIO.jpg -------------------------------------------------------------------------------- /sensor/raspberrypi/README.md: -------------------------------------------------------------------------------- 1 | # air_monitor 2 | ## 树莓派 3 | ### 要点: 4 | 1. 树莓派的串口是默认当调试口的,所以一定要关闭后才能正常使用该串口:http://blog.csdn.net/xukai871105/article/details/22713925 5 | 2. sudo apt-get install python-pycurl 6 | 3. sudo pip install --upgrade --trusted-host wxpython.org --pre -f http://wxpython.org/Phoenix/snapshot-builds/ wxPython_Phoenix 7 | import wx 8 | -------------------------------------------------------------------------------- /sensor/raspberrypi/color.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | white = pygame.Color(255, 255, 255) 4 | black = pygame.Color(0, 0, 0) 5 | grey = pygame.Color(120, 120, 120) 6 | red = pygame.Color(255, 0, 0) 7 | green = pygame.Color(0, 255, 0) 8 | blue = pygame.Color(0, 0, 255) 9 | pink = pygame.Color(255, 0, 156) 10 | -------------------------------------------------------------------------------- /sensor/raspberrypi/dashboard.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | import pygame 4 | import color 5 | import math 6 | 7 | if ~pygame.font.get_init(): 8 | pygame.font.init() 9 | 10 | 11 | class DASHBOARD(pygame.sprite.Sprite): 12 | def __init__(self, surface, position, radius, name, color_bg, least, highest): 13 | pygame.sprite.Sprite.__init__(self) 14 | self.surface = surface 15 | self.radius = radius 16 | self.line_width = int(math.ceil(self.radius / 9.0)) 17 | self.gap = int(max(math.ceil(self.line_width / 5.0), 2)) 18 | self.arc_width = self.line_width 19 | self.position = position 20 | self.name = name.decode('utf-8', 'ignore').encode('gbk') 21 | # print self.name 22 | self.font_width = int(self.arc_width * 1.5) 23 | # self.font = pygame.font.SysFont('楷体', self.font_width) 24 | self.font = pygame.font.Font(None, self.font_width) 25 | self.rect = (self.position[0] - self.radius, self.position[1] - self.radius, self.radius * 2, self.radius * 2) 26 | self.color_bg = color_bg 27 | self.least = least 28 | self.highest = int(highest / 10.0 * 12) 29 | self.scale_gap = int(self.gap / 4.0 * 3) 30 | self.needle_length = self.radius - self.line_width - self.arc_width - self.font_width - (self.gap) * 5 31 | self.needle_width = int(max(self.arc_width / 2.0, 4)) 32 | self.origin_radius = int(self.arc_width / 2.0) 33 | self.origin_gap = int(self.scale_gap / 2.0) 34 | self.color_start = color.green 35 | self.color_end = color.red 36 | 37 | def draw(self, value): 38 | self.draw_blendcolor_arc(self.radius, self.line_width, color.grey, color.grey, 0, 360, 20) 39 | self.draw_blendcolor_arc(self.radius - self.line_width - self.gap, self.arc_width, self.color_end, 40 | self.color_start, -60, 41 | 232, 10) 42 | self.draw_scale(self.least, self.highest, self.line_width, self.color_bg, color.white) 43 | self.draw_needle(value, color.red) 44 | 45 | temp_distance = 0 46 | temp_pos = 0 47 | old_font_width = self.font_width 48 | # print self.name 49 | if (self.name == '甲醛'): 50 | # print self.name 51 | # self.font_width = self.font_width / 4 * 3 52 | self.font = pygame.font.Font('wts11.ttf', self.font_width) 53 | temp_distance = self.font_width / 3 54 | temp_pos = 0 55 | elif (self.name == '易燃气体'): 56 | self.font = pygame.font.Font('wts11.ttf', self.font_width) 57 | temp_distance = self.font_width / 3 58 | temp_pos = self.font_width / 2 59 | text_name = self.font.render(self.name.decode('utf-8', 'ignore'), True, color.white) 60 | distance_text_name = self.radius - self.line_width - self.gap - self.font_width - temp_distance 61 | self.surface.blit(text_name, ( 62 | self.position[0] - len(self.name) * self.font_width / 5 + temp_pos, self.position[1] + distance_text_name)) 63 | temp_distance = 0 64 | temp_pos = 0 65 | self.font_width = old_font_width 66 | self.font = pygame.font.Font(None, self.font_width) 67 | 68 | self.font_width = old_font_width / 2 * 3 69 | self.font = pygame.font.Font(None, self.font_width) 70 | str_value = "%.2f" % value 71 | color_gap = (self.color_end.r - self.color_start.r, self.color_end.g - self.color_start.g, 72 | self.color_end.b - self.color_start.b) 73 | text_color = [self.color_start[0], self.color_start[1], self.color_start[2]] 74 | text_color[0] = int( 75 | self.color_start[0] + (self.color_end[0] - self.color_start[0]) * 1.0 / (self.highest - self.least) * ( 76 | value - self.least)) 77 | if (text_color[0] < 0): 78 | text_color[0] = 0 79 | elif (text_color[0] > 255): 80 | text_color[0] = 255 81 | text_color[1] = int( 82 | self.color_start[1] + (self.color_end[1] - self.color_start[1]) * 1.0 / (self.highest - self.least) * ( 83 | value - self.least)) 84 | if (text_color[1] < 0): 85 | text_color[1] = 0 86 | elif (text_color[1] > 255): 87 | text_color[1] = 255 88 | text_color[2] = int( 89 | self.color_start[2] + (self.color_end[2] - self.color_start[2]) * 1.0 / (self.highest - self.least) * ( 90 | value - self.least)) 91 | if (text_color[2] < 0): 92 | text_color[2] = 0 93 | elif (text_color[2] > 255): 94 | text_color[2] = 255 95 | # print text_color[0], text_color[1], text_color[2], self.name, value, self.least 96 | temp_color = pygame.Color(text_color[0], text_color[1], text_color[2]) 97 | text_value = self.font.render(str_value, True, temp_color) 98 | # distance_text_value = self.radius - self.line_width - self.arc_width - self.font_width * 2 - (self.gap) * 6 99 | distance_text_value = self.radius - self.line_width - self.arc_width - self.font_width / 6 * 9 - (self.gap) * 6 100 | # self.surface.blit(text_value, (self.position[0] - self.font_width, self.position[1] + distance_text_value)) 101 | self.surface.blit(text_value, ( 102 | self.position[0] - len(str_value) * self.font_width / 6, self.position[1] + distance_text_value)) 103 | self.font_width = old_font_width 104 | self.font = pygame.font.Font(None, self.font_width) 105 | 106 | def draw_blendcolor_arc(self, radius, width, color_start, color_end, degree_start, degree_stop, step): 107 | color_gap = (color_end.r - color_start.r, color_end.g - color_start.g, color_end.b - color_start.b) 108 | color_i = [color_start[0], color_start[1], color_start[2]] 109 | rect = (self.position[0] - radius, self.position[1] - radius, radius * 2, radius * 2) 110 | for degree in range(degree_start, degree_stop + 1): 111 | color_i[0] = int( 112 | color_start[0] + color_gap[0] * 1.0 / (degree_stop - degree_start) * (degree - degree_start)) 113 | color_i[1] = int( 114 | color_start[1] + color_gap[1] * 1.0 / (degree_stop - degree_start) * (degree - degree_start)) 115 | color_i[2] = int( 116 | color_start[2] + color_gap[2] * 1.0 / (degree_stop - degree_start) * (degree - degree_start)) 117 | pygame.draw.arc(self.surface, color_i, rect, math.radians(degree), math.radians(degree + step), width) 118 | 119 | def draw_scale(self, least, highest, width, color_bg, color_number): 120 | step = (highest - least) / 12 121 | gap_number = [self.font_width / 3 * 1, self.font_width / 3 * 1, 0, self.font_width / 12 * 1, 122 | self.font_width / 20 * 1, self.font_width / 20, self.font_width / 8 * 5, self.font_width / 2 * 2, 123 | self.font_width / 4 * 5, self.font_width / 3 * 4, self.font_width / 4 * 4] 124 | degree_offset_number = [-3, -2, -3, -3, 3, 6, 5, 8, 3, -2, -8] 125 | for i in range(0, 11): 126 | degree = 240 + i * (-30) 127 | rate_cos = math.cos(math.radians(degree)) 128 | rate_sin = math.sin(math.radians(degree)) 129 | pygame.draw.line(self.surface, color_bg, 130 | (self.position[0] + rate_cos * self.radius, self.position[1] - rate_sin * self.radius), ( 131 | self.position[0] + rate_cos * (self.radius - width), 132 | self.position[1] - rate_sin * (self.radius - width)), self.scale_gap) 133 | number = i * step + least 134 | rate_cos = math.cos(math.radians(degree + degree_offset_number[i])) 135 | rate_sin = math.sin(math.radians(degree + degree_offset_number[i])) 136 | text_number = self.font.render(str(number), True, color_number) 137 | radius_number = self.radius - self.line_width - self.arc_width - (self.gap) * 2 - gap_number[i] 138 | self.surface.blit(text_number, ( 139 | self.position[0] + rate_cos * radius_number, self.position[1] - rate_sin * radius_number)) 140 | 141 | def draw_needle(self, value, color_needle): 142 | degree = 240 - (value - self.least) * 1.0 / (self.highest - self.least) * 360 143 | rate_cos = math.cos(math.radians(degree)) 144 | rate_sin = math.sin(math.radians(degree)) 145 | position_end = ( 146 | int(self.position[0] + rate_cos * self.needle_length), 147 | int(self.position[1] - rate_sin * self.needle_length)) 148 | pygame.draw.line(self.surface, color_needle, self.position, position_end, self.needle_width) 149 | pygame.draw.circle(self.surface, color_needle, position_end, int(self.needle_width / 24.0 * 14), 0) 150 | pygame.draw.circle(self.surface, color.white, self.position, self.origin_radius, 0) 151 | pygame.draw.circle(self.surface, self.color_bg, self.position, self.origin_radius - self.origin_gap, 1) 152 | -------------------------------------------------------------------------------- /sensor/raspberrypi/sensor.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import time 3 | import sensor_api 4 | import yeelink_config 5 | import yeelink_api 6 | 7 | import pygame 8 | import sys 9 | from pygame.locals import * 10 | import dashboard 11 | import color 12 | import random 13 | from time import time 14 | 15 | import pycurl 16 | 17 | _DEBUG_ = False 18 | 19 | MYID = 0 20 | yeelink_config.init(MYID) 21 | device_id = yeelink_config.device_id() 22 | apikey = yeelink_config.apikey() 23 | 24 | time_old = time() 25 | 26 | pygame.init() 27 | pygame.display.set_caption("Demo") 28 | clock = pygame.time.Clock() 29 | 30 | # count = 0 31 | 32 | try: 33 | import wx 34 | 35 | size = wx.GetDisplaySize() 36 | except: 37 | print "Can't find wxpython." 38 | size = pygame.display.list_modes()[len(pygame.display.list_modes()) / 2] 39 | 40 | gap = (int(size[0] / 14), int(size[1] / 9)) 41 | radius = min(gap[0], gap[1]) * 2 42 | size = (2 * gap[0] + 6 * radius, gap[1] + 4 * radius) 43 | 44 | # print size 45 | 46 | screen = pygame.display.set_mode(size, FULLSCREEN | HWSURFACE) 47 | 48 | color_bg = color.black 49 | 50 | x_mydashboard = 3 51 | y_mydashboard = 2 52 | mydashboard = {} 53 | values = {} 54 | names = ['PM2.5', 'CO', 'SO2', 'O3', '甲醛'.decode('gbk', 'ignore').encode('utf-8'), 55 | '易燃气体'.decode('gbk', 'ignore').encode('utf-8')] 56 | values_range = {} 57 | values_range[names[0]] = (0, 500) 58 | values_range[names[1]] = (0, 200) 59 | values_range[names[2]] = (0, 100) 60 | values_range[names[3]] = (0, 100) 61 | values_range[names[4]] = (0, 1000) 62 | values_range[names[5]] = (0, 1000) 63 | 64 | for y in range(0, y_mydashboard): 65 | for x in range(0, x_mydashboard): 66 | position = (radius + x * (gap[0] + 2 * radius), radius + y * (gap[1] + 2 * radius)) 67 | # mydashboard.append(dashboard.DASHBOARD(screen, position, radius, names[x + y * x_mydashboard], color_bg, 0, 1000)) 68 | mydashboard[names[x + y * x_mydashboard]] = dashboard.DASHBOARD(screen, position, radius, 69 | names[x + y * x_mydashboard], color_bg, 70 | values_range[names[x + y * x_mydashboard]][0], 71 | values_range[names[x + y * x_mydashboard]][1]) 72 | values[names[x + y * x_mydashboard]] = 0.0 73 | 74 | # values['甲醛'.decode('gbk', 'ignore').encode('utf-8')] = 0.06 75 | # values['易燃气体'.decode('gbk', 'ignore').encode('utf-8')] = 1.35 76 | 77 | pygame.mouse.set_visible(False) 78 | 79 | while True: 80 | for event in pygame.event.get(): 81 | if event.type == pygame.QUIT: 82 | sys.exit() 83 | elif event.type == KEYUP: 84 | if event.key == K_ESCAPE: 85 | sys.exit() 86 | 87 | value_pm25 = sensor_api.read_value('PM2.5') 88 | if value_pm25 > 0: 89 | # print "pm2.5 :", value_pm25 90 | values['PM2.5'] = value_pm25 91 | 92 | value_CO = sensor_api.read_value('CO') 93 | if value_CO > 0: 94 | # print "CO :", value_CO 95 | values['CO'] = value_CO 96 | 97 | value_SO2 = sensor_api.read_value('SO2') 98 | if value_SO2 > 0: 99 | # print "SO2 :", value_SO2 100 | values['SO2'] = value_SO2 101 | 102 | value_O3 = sensor_api.read_value('O3') 103 | if value_O3 > 0: 104 | # print "O3 :", value_O3 105 | values['O3'] = value_O3 106 | # values['O3'] = 0 107 | 108 | value_HCHO = sensor_api.read_value('HCHO') 109 | if value_HCHO > 0: 110 | values['甲醛'.decode('gbk', 'ignore').encode('utf-8')] = value_HCHO 111 | 112 | value_MQ2 = sensor_api.read_value('MQ2') 113 | if value_MQ2 > 0: 114 | values['易燃气体'.decode('gbk', 'ignore').encode('utf-8')] = value_MQ2 115 | 116 | time_now = time() 117 | if time_now - time_old > 10: 118 | # print "tick", time_now - time_old 119 | time_old = time_now 120 | 121 | if not _DEBUG_: 122 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_pm25_id(), values['PM2.5']) 123 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_CO_id(), values['CO']) 124 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_SO2_id(), values['SO2']) 125 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_O3_id(), values['O3']) 126 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_HCHO_id(), 127 | values['甲醛'.decode('gbk', 'ignore').encode('utf-8')]) 128 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_MQ2_id(), 129 | values['易燃气体'.decode('gbk', 'ignore').encode('utf-8')]) 130 | 131 | mycurl = pycurl.Curl() 132 | mycurl.setopt(mycurl.URL, 'http://www.zhangshengdong.com/weixin/warningtemplate.php') 133 | try: 134 | mycurl.perform() 135 | except Exception, e: 136 | print Exception, ":", e 137 | # print "" 138 | mycurl.close() 139 | 140 | # print "" 141 | 142 | screen.fill(color_bg) 143 | 144 | for y in range(0, y_mydashboard): 145 | for x in range(0, x_mydashboard): 146 | mydashboard[names[x + y * x_mydashboard]].draw(values[names[x + y * x_mydashboard]]) 147 | 148 | pygame.display.flip() 149 | clock.tick(10) 150 | -------------------------------------------------------------------------------- /sensor/raspberrypi/sensor_api.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import RPi.GPIO as GPIO 3 | import serial 4 | import smbus 5 | 6 | _DEBUG_ = False 7 | 8 | 9 | class SENSOR_CONFIG(): 10 | serial_0 = serial.Serial("/dev/ttyUSB0", 9600) 11 | value_pm = -1 12 | value_CO = -1 13 | value_SO2 = -1 14 | value_O3 = -1 15 | value_HCHO = -1 16 | value_MQ2 = -1 17 | 18 | 19 | GPIO.setmode(GPIO.BOARD) 20 | 21 | sensor_config = SENSOR_CONFIG() 22 | 23 | 24 | def read_value(sensor_name): 25 | waitlen = sensor_config.serial_0.inWaiting() 26 | if waitlen != 0: 27 | recv = sensor_config.serial_0.read(waitlen) 28 | recv = bytes(recv) 29 | #print(recv) 30 | try: 31 | recv_split = recv.split('\n') 32 | except: 33 | recv_split = recv.split(b'\n') 34 | #print(recv_split) 35 | for message in recv_split: 36 | try: 37 | message_split = message.split(':') 38 | except: 39 | message_split = message.split(b':') 40 | #print(message_split) 41 | if len(message_split) > 1: 42 | name = message_split[0] 43 | value_str = message_split[1] 44 | try: 45 | value = float(value_str.strip()) 46 | # print name, "--", value 47 | except: 48 | continue 49 | #print(sensor_name,name,value) 50 | if value > 0: 51 | if name == b"PM2.5": 52 | sensor_config.value_pm = value 53 | if sensor_name == "PM2.5": 54 | return sensor_config.value_pm 55 | elif name == b"CO": 56 | sensor_config.value_CO = value 57 | if sensor_name == "CO": 58 | return sensor_config.value_CO 59 | elif name == b"SO2": 60 | sensor_config.value_SO2 = value 61 | if sensor_name == "SO2": 62 | return sensor_config.value_SO2 63 | elif name == b"O3": 64 | sensor_config.value_O3 = value 65 | if sensor_name == "O3": 66 | return sensor_config.value_O3 67 | elif name == b"HCHO": 68 | sensor_config.value_HCHO = value 69 | if sensor_name == "HCHO": 70 | return sensor_config.value_HCHO 71 | elif name == b"MQ2": 72 | sensor_config.value_MQ2 = value 73 | if sensor_name == "MQ2": 74 | return sensor_config.value_MQ2 75 | if sensor_name == "PM2.5": 76 | return sensor_config.value_pm 77 | elif sensor_name == "CO": 78 | return sensor_config.value_CO 79 | elif sensor_name == "SO2": 80 | return sensor_config.value_SO2 81 | elif sensor_name == "O3": 82 | return sensor_config.value_O3 83 | elif sensor_name == "HCHO": 84 | return sensor_config.value_HCHO 85 | else: 86 | return sensor_config.value_MQ2 87 | -------------------------------------------------------------------------------- /sensor/raspberrypi/sensor_api_old.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | import RPi.GPIO as GPIO 4 | import serial 5 | import smbus 6 | 7 | _DEBUG_ = False 8 | 9 | 10 | class SENSOR_CONFIG(): 11 | serial_0 = serial.Serial("/dev/ttyS0", 2400) 12 | A = 1200 13 | 14 | address = 0x48 15 | # 元件上的标号是反的,A0应该在A2的位置,另外A3貌似没用 16 | #A0 = 0x40 17 | #A1 = 0x41 18 | #A2 = 0x42 19 | #A3 = 0x43 20 | A0 = 0x00 21 | A1 = 0x01 22 | A2 = 0x02 23 | A3 = 0x03 24 | 25 | bus = smbus.SMBus(1) 26 | 27 | 28 | GPIO.setmode(GPIO.BOARD) 29 | 30 | sensor_config = SENSOR_CONFIG() 31 | 32 | 33 | def read_pm25(): 34 | result = -1 35 | Vout_H = 0 36 | Vout_L = 0 37 | Vret_H = 0 38 | Vret_L = 0 39 | check = 0 40 | waitlen = sensor_config.serial_0.inWaiting() 41 | if _DEBUG_: 42 | print "waitlen : sensor_api", waitlen 43 | if waitlen != 0: 44 | recv = sensor_config.serial_0.read(waitlen) 45 | listhex = [ord(i) for i in recv] 46 | if _DEBUG_: 47 | print listhex 48 | count = 0 49 | old_i = 0 50 | i = 0 51 | while i < len(listhex) - 1: 52 | # for i in range(len(listhex)): 53 | if count == 0: 54 | if listhex[i] == 170: 55 | old_i = i 56 | count += 1 57 | Vout_H = 0 58 | Vout_L = 0 59 | Vret_H = 0 60 | Vret_L = 0 61 | check = 0 62 | else: 63 | count += 1 64 | if count == 2: 65 | Vout_H = listhex[i] 66 | elif count == 3: 67 | Vout_L = listhex[i] 68 | elif count == 4: 69 | Vret_H = listhex[i] 70 | elif count == 5: 71 | Vret_L = listhex[i] 72 | elif count == 6: 73 | check = listhex[i] 74 | elif count == 7: 75 | count = 0 76 | if _DEBUG_: 77 | print Vout_H, Vout_L, Vret_H, Vret_L, check, listhex[i] 78 | if listhex[i] == 255: 79 | if check == (Vout_H + Vout_L + Vret_H + Vret_L) % 256: 80 | Vout = (Vout_H * 256 + Vout_L) * 1.0 / 1024 * 5 81 | Ud = 1.0 * sensor_config.A * Vout 82 | if _DEBUG_: 83 | print Vout, Ud 84 | if Ud > 0: 85 | result = Ud 86 | break 87 | i = old_i 88 | i += 1 89 | return result 90 | 91 | 92 | def read_CO(): 93 | sensor_config.bus.write_byte(sensor_config.address, sensor_config.A0) 94 | value_CO = sensor_config.bus.read_byte(sensor_config.address) * 1.0 / 256 * 1000 95 | if value_CO > 0: 96 | return value_CO 97 | else: 98 | return -1 99 | 100 | 101 | def read_SO2(): 102 | sensor_config.bus.write_byte(sensor_config.address, sensor_config.A1) 103 | value_SO2 = sensor_config.bus.read_byte(sensor_config.address) * 1.0 / 256 * 500 104 | if value_SO2 > 0: 105 | return value_SO2 106 | else: 107 | return -1 108 | 109 | 110 | def read_O3(): 111 | sensor_config.bus.write_byte(sensor_config.address, sensor_config.A2) 112 | value_O3 = sensor_config.bus.read_byte(sensor_config.address) * 1.0 / 256 * 1000 113 | if value_O3 > 0: 114 | return value_O3 115 | else: 116 | return -1 117 | -------------------------------------------------------------------------------- /sensor/raspberrypi/sensor_backup.py: -------------------------------------------------------------------------------- 1 | import time 2 | import sensor_api 3 | import yeelink_config 4 | import yeelink_api 5 | 6 | _DEBUG_ = True 7 | 8 | MYID = 1 9 | yeelink_config.init(MYID) 10 | device_id = yeelink_config.device_id() 11 | apikey = yeelink_config.apikey() 12 | 13 | while True: 14 | value_pm25 = sensor_api.read_pm25() 15 | if value_pm25 > 0: 16 | print "pm2.5 :", value_pm25 17 | if not _DEBUG_: 18 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_pm25_id(), value_pm25) 19 | 20 | value_CO = sensor_api.read_CO() 21 | if value_CO > 0: 22 | print "CO :", value_CO 23 | if not _DEBUG_: 24 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_CO_id(), value_CO) 25 | 26 | value_SO2 = sensor_api.read_SO2() 27 | if value_SO2 > 0: 28 | print "SO2 :", value_SO2 29 | if not _DEBUG_: 30 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_SO2_id(), value_SO2) 31 | 32 | value_O3 = sensor_api.read_O3() 33 | if value_O3 > 0: 34 | print "O3 :", value_O3 35 | if not _DEBUG_: 36 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_O3_id(), value_O3) 37 | 38 | print "" 39 | 40 | # print "sleep" 41 | time.sleep(15) 42 | -------------------------------------------------------------------------------- /sensor/raspberrypi/sensor_old.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import time 3 | import sensor_api 4 | import yeelink_config 5 | import yeelink_api 6 | 7 | import pygame 8 | import sys 9 | from pygame.locals import * 10 | import dashboard 11 | import color 12 | import random 13 | from time import time 14 | 15 | import pycurl 16 | 17 | import RPi.GPIO as GPIO 18 | # BOARD编号方式,基于插座引脚编号 19 | GPIO.setmode(GPIO.BOARD) 20 | # 输出模式 21 | GPIO.setup(17,GPIO.OUT) 22 | GPIO.setup(18,GPIO.OUT) 23 | GPIO.output(17,GPIO.HIGH) 24 | GPIO.output(18,GPIO.LOW) 25 | 26 | _DEBUG_ = True 27 | 28 | MYID = 0 29 | yeelink_config.init(MYID) 30 | device_id = yeelink_config.device_id() 31 | apikey = yeelink_config.apikey() 32 | 33 | time_old = time() 34 | 35 | pygame.init() 36 | pygame.display.set_caption("Demo") 37 | clock = pygame.time.Clock() 38 | 39 | try: 40 | import wx 41 | 42 | size = wx.GetDisplaySize() 43 | except: 44 | print "Can't find wxpython." 45 | size = pygame.display.list_modes()[len(pygame.display.list_modes()) / 2] 46 | 47 | gap = (int(size[0] / 14), int(size[1] / 9)) 48 | radius = min(gap[0], gap[1]) * 2 49 | size = (2 * gap[0] + 6 * radius, gap[1] + 4 * radius) 50 | 51 | # print size 52 | 53 | screen = pygame.display.set_mode(size, FULLSCREEN | HWSURFACE) 54 | 55 | color_bg = color.black 56 | 57 | x_mydashboard = 3 58 | y_mydashboard = 2 59 | mydashboard = {} 60 | values = {} 61 | names = ['PM2.5', 'CO', 'SO2', 'O3', '甲醛'.decode('gbk', 'ignore').encode('utf-8'), 62 | '易燃气体'.decode('gbk', 'ignore').encode('utf-8')] 63 | values_range = {} 64 | values_range[names[0]] = (0, 500) 65 | values_range[names[1]] = (0, 200) 66 | values_range[names[2]] = (0, 50) 67 | values_range[names[3]] = (0, 50) 68 | values_range[names[4]] = (0, 1000) 69 | values_range[names[5]] = (0, 1000) 70 | 71 | for y in range(0, y_mydashboard): 72 | for x in range(0, x_mydashboard): 73 | position = (radius + x * (gap[0] + 2 * radius), radius + y * (gap[1] + 2 * radius)) 74 | # mydashboard.append(dashboard.DASHBOARD(screen, position, radius, names[x + y * x_mydashboard], color_bg, 0, 1000)) 75 | mydashboard[names[x + y * x_mydashboard]] = dashboard.DASHBOARD(screen, position, radius, 76 | names[x + y * x_mydashboard], color_bg, 77 | values_range[names[x + y * x_mydashboard]][0], 78 | values_range[names[x + y * x_mydashboard]][1]) 79 | values[names[x + y * x_mydashboard]] = 0.0 80 | 81 | values['甲醛'.decode('gbk', 'ignore').encode('utf-8')] = 0.06 82 | values['易燃气体'.decode('gbk', 'ignore').encode('utf-8')] = 1.35 83 | 84 | while True: 85 | for event in pygame.event.get(): 86 | if event.type == pygame.QUIT: 87 | sys.exit() 88 | elif event.type == KEYUP: 89 | if event.key == K_ESCAPE: 90 | sys.exit() 91 | 92 | value_pm25 = sensor_api.read_pm25() 93 | if value_pm25 > 0: 94 | # print "pm2.5 :", value_pm25 95 | values['PM2.5'] = value_pm25 96 | 97 | value_CO = sensor_api.read_CO() 98 | if value_CO > 0: 99 | # print "CO :", value_CO 100 | values['CO'] = value_CO 101 | 102 | value_SO2 = sensor_api.read_SO2() 103 | if value_SO2 > 0: 104 | # print "SO2 :", value_SO2 105 | values['SO2'] = value_SO2 106 | 107 | value_O3 = sensor_api.read_O3() 108 | if value_O3 > 0: 109 | # print "O3 :", value_O3 110 | values['O3'] = value_O3 111 | # values['O3'] = 0 112 | 113 | time_now = time() 114 | if time_now - time_old > 15: 115 | # print "tick", time_now - time_old 116 | time_old = time_now 117 | 118 | if not _DEBUG_: 119 | print "send value", values['CO'], values['SO2'] 120 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_pm25_id(), values['PM2.5']) 121 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_CO_id(), values['CO']) 122 | yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_SO2_id(), values['SO2']) 123 | # yeelink_api.send_value(apikey, device_id, yeelink_config.sensor_O3_id(), values['O3']) 124 | 125 | mycurl = pycurl.Curl() 126 | mycurl.setopt(mycurl.URL, 'http://www.zhangshengdong.com/weixin/warningtemplate.php') 127 | try: 128 | mycurl.perform() 129 | except Exception, e: 130 | print Exception, ":", e 131 | mycurl.close() 132 | 133 | # print "" 134 | 135 | screen.fill(color_bg) 136 | 137 | for y in range(0, y_mydashboard): 138 | for x in range(0, x_mydashboard): 139 | mydashboard[names[x + y * x_mydashboard]].draw(values[names[x + y * x_mydashboard]]) 140 | 141 | pygame.display.flip() 142 | clock.tick(10) 143 | -------------------------------------------------------------------------------- /sensor/raspberrypi/shell.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import sensor_api 3 | from time import time as time_func 4 | import time 5 | import os 6 | import sys 7 | import serial 8 | 9 | path_BEIDOU = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "beidou") 10 | sys.path.append(path_BEIDOU) 11 | from beidou import TXA 12 | 13 | serial_BEIDOU = serial.Serial("/dev/ttyUSB1", 115200) 14 | txa = TXA(user_address='0247718', serial=serial_BEIDOU, transfer_method='1') 15 | txa.read() 16 | 17 | _DEBUG_ = False 18 | 19 | time_old = time_func() 20 | 21 | values = {} 22 | names = ['PM2.5', 'CO', 'SO2', 'O3', 'HCHO', 'MQ2'] 23 | 24 | txa.send(b"$CCICI,0,00*73\r\n") 25 | 26 | while True: 27 | 28 | value_pm25 = sensor_api.read_value('PM2.5') 29 | if value_pm25 > 0: 30 | # print("\t\tpm2.5 :", value_pm25) 31 | values['PM25'] = value_pm25 32 | 33 | value_CO = sensor_api.read_value('CO') 34 | if value_CO > 0: 35 | # print("\t\tCO :", value_CO) 36 | values['CO'] = value_CO 37 | 38 | value_SO2 = sensor_api.read_value('SO2') 39 | if value_SO2 > 0: 40 | # print("\t\tSO2 :", value_SO2) 41 | values['SO2'] = value_SO2 42 | 43 | value_O3 = sensor_api.read_value('O3') 44 | if value_O3 > 0: 45 | # print("\t\tO3 :", value_O3) 46 | values['O3'] = value_O3 47 | 48 | value_HCHO = sensor_api.read_value('HCHO') 49 | if value_HCHO > 0: 50 | # print("\t\tHCHO :", value_HCHO) 51 | values['HCHO'] = value_HCHO 52 | 53 | value_MQ2 = sensor_api.read_value('MQ2') 54 | if value_MQ2 > 0: 55 | # print("\t\tMQ2 :", value_MQ2) 56 | values['MQ2'] = value_MQ2 57 | 58 | time_now = time_func() 59 | if time_now - time_old > 60: 60 | time_old = time_now 61 | '''content = "PM2.5:" + values['PM25'] + ",CO:" + values['CO'] + ",SO2:" + values['SO2'] + ",O3:" + values[ 62 | 'O3'] + ",HCHO:" + values['HCHO'] + ",MQ2:" + values['MQ2']''' 63 | content = "PM25" + str(value_pm25) + "CO" + str(value_CO) + "SO2" + str(value_SO2) + "O3" + str( 64 | value_O3) + "HCHO" + str(value_HCHO) + "MQ2" + str(value_MQ2) 65 | '''content = "PM2.5-" + str(values['PM25']) + "--CO-" + str(values['CO']) + "--SO2-" + str(values['SO2']) + "--O3-" + str( 66 | values['O3']) + "--HCHO-" + str(value_HCHO) + "--MQ2-" + str(value_MQ2)''' 67 | message = txa.message(content=content) 68 | print("\t\t", message) 69 | txa.send(message=message) 70 | 71 | time.sleep(1) 72 | -------------------------------------------------------------------------------- /sensor/raspberrypi/test.py: -------------------------------------------------------------------------------- 1 | import serial 2 | import time 3 | 4 | serial_0 = serial.Serial("/dev/ttyUSB0", 9600) 5 | 6 | while True: 7 | waitlen = serial_0.inWaiting() 8 | if waitlen != 0: 9 | recv = serial_0.read(waitlen) 10 | recv_split = recv.split('\n') 11 | for message in recv_split: 12 | message_split = message.split(':') 13 | if len(message_split) > 1: 14 | name = message_split[0] 15 | value_str = message_split[1] 16 | try: 17 | value = float(value_str) 18 | print name, "--", value 19 | except: 20 | pass 21 | time.sleep(0.1) 22 | -------------------------------------------------------------------------------- /sensor/raspberrypi/test1.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | def XOR_CheckSum_string(m_str, encoding="ascii"): 4 | if str == type(m_str): 5 | try: 6 | m_str = bytes(m_str, encoding=encoding) 7 | except: 8 | # m_str = bytes(m_str) 9 | m_str = m_str.encode(encoding=encoding) 10 | sum = 0x0 11 | # print(m_str) 12 | # print(type(m_str)) 13 | for c in m_str: 14 | try: 15 | sum = sum ^ c 16 | except: 17 | # print(c) 18 | sum = sum ^ ord(c) 19 | sum = sum ^ 0x0 20 | return sum 21 | 22 | msg = b'\xb3\xb1\xb3\xb2\xb3\xb3\xb3\xb4\xb3\xb5' 23 | print(msg) 24 | print(str(msg)) 25 | print(msg.decode('GB18030').encode('utf-8')) 26 | print(msg.decode('GBK')) 27 | print(msg.decode('GB2312')) 28 | print(msg.decode('utf-16')) 29 | # print(msg.decode('utf-8')) 30 | 31 | msg = b'\xB9\xE3\xD6\xDD\xBA\xA3\xC1\xC4\xBF\xC6\xBC\xBC\xD3\xD0\xCF\xDE\xB9\xAB\xCB\xBE' 32 | print(msg.decode('GB2312')) 33 | 34 | print("广州海聊科技有限公司".encode(encoding="gb2312")) 35 | print(bytes("广州海聊科技有限公司", 'gb2312')) 36 | print(b'\xA4' + bytes("广州海聊科技..有限公--司12就3a给bc.-", 'gb2312')) 37 | print((b'\xA4' + bytes("广州海聊科技..有限公--司12就3a给bc.-", 'gb2312'))[1:]) 38 | 39 | # msg=b'\xb9\xe3\xd6\xdd\xba\xa3\xc1\xc4\xbf\xc6\xbc\xbc..\xd3\xd0\xcf\xde\xb9\xab--\xcb\xbe12\xbe\xcd3a\xb8\xf8bc.-' 40 | msg = (b'\xA4' + bytes("广州海聊科技..有限公--司12就3a给bc.-", 'gb2312'))[1:] 41 | print(msg.decode('GB2312')) 42 | 43 | print(bytes("\xA4广州海聊科技有限公司", 'gb2312')) 44 | 45 | test_msg=bytes("CCTXA,0242407,1,2,",'gb2312')+b'\xA4'+bytes("广州海聊科技有限公司", 'gb2312') 46 | #test_msg=b'$CCTXA,0242407,1,2,A4B9E3D6DDBAA3C1C4BFC6BCBCD3D0CFDEB9ABCBBE*0F' 47 | print(test_msg) 48 | print(hex(XOR_CheckSum_string(test_msg))) 49 | 50 | print(hex(XOR_CheckSum_string(bytes("CCTXA,0242407,1,2,",'utf-8')+bytes("0123456789ABCDEF", 'utf-8')))) 51 | -------------------------------------------------------------------------------- /sensor/raspberrypi/test_pygame.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import pygame 3 | import sys 4 | from pygame.locals import * 5 | import dashboard 6 | import color 7 | import random 8 | from time import time 9 | 10 | time_old = time() 11 | 12 | pygame.init() 13 | pygame.display.set_caption("Demo") 14 | clock = pygame.time.Clock() 15 | 16 | try: 17 | import wx 18 | 19 | size = wx.GetDisplaySize() 20 | except: 21 | print "Can't find wxpython." 22 | size = pygame.display.list_modes()[len(pygame.display.list_modes()) / 2] 23 | 24 | gap = (int(size[0] / 14), int(size[1] / 9)) 25 | radius = min(gap[0], gap[1]) * 2 26 | size = (2 * gap[0] + 6 * radius, gap[1] + 4 * radius) 27 | 28 | # print size 29 | 30 | screen = pygame.display.set_mode(size, FULLSCREEN | HWSURFACE) 31 | 32 | color_bg = color.black 33 | 34 | x_mydashboard = 3 35 | y_mydashboard = 2 36 | mydashboard = [] 37 | 38 | names = ['PM2.5', 'CO', 'SO2', 'O3', '甲醛'.decode('gbk', 'ignore').encode('utf-8'), '易燃气体'.decode('gbk', 'ignore').encode('utf-8')] 39 | 40 | for y in range(0, y_mydashboard): 41 | for x in range(0, x_mydashboard): 42 | position = (radius + x * (gap[0] + 2 * radius), radius + y * (gap[1] + 2 * radius)) 43 | mydashboard.append( 44 | dashboard.DASHBOARD(screen, position, radius, names[x + y * x_mydashboard], color_bg, 0, 1000)) 45 | 46 | while True: 47 | for event in pygame.event.get(): 48 | if event.type == pygame.QUIT: 49 | sys.exit() 50 | elif event.type == KEYUP: 51 | if event.key == K_ESCAPE: 52 | sys.exit() 53 | 54 | time_now = time() 55 | if time_now - time_old > 15: 56 | print "tick", time_now - time_old 57 | time_old = time_now 58 | 59 | screen.fill(color_bg) 60 | 61 | for i in range(0, x_mydashboard * y_mydashboard): 62 | mydashboard[i].draw(random.uniform(0, 1000)) 63 | 64 | pygame.display.flip() 65 | # pygame.time.delay(100) 66 | clock.tick(5) 67 | -------------------------------------------------------------------------------- /sensor/raspberrypi/test_tkinter.py: -------------------------------------------------------------------------------- 1 | from Tkinter import * 2 | 3 | class Application(Frame): 4 | def say_hi(self): 5 | print "hi there, everyone!" 6 | 7 | def print_contents(self, event): 8 | print "hi. contents of entry is now ---->", self.contents.get() 9 | 10 | def createWidgets(self): 11 | self.QUIT = Button(self) 12 | self.QUIT["text"] = "QUIT" 13 | self.QUIT["fg"] = "red" 14 | self.QUIT["command"] = self.quit 15 | self.QUIT.pack({"side": "left"}) 16 | 17 | self.hi_there = Button(self) 18 | self.hi_there["text"] = "Hello", 19 | self.hi_there["command"] = self.say_hi 20 | self.hi_there.pack({"side": "left"}) 21 | 22 | self.contents = StringVar() 23 | self.contents.set("this is a variable") 24 | 25 | self.entrythingy = Entry() 26 | self.entrythingy.pack() 27 | self.entrythingy["textvariable"] = self.contents 28 | self.entrythingy.bind('',self.print_contents) #Enter 29 | 30 | def __init__(self, master=None): 31 | Frame.__init__(self, master) 32 | self.pack() 33 | self.createWidgets() 34 | 35 | 36 | 37 | 38 | 39 | root = Tk() 40 | app = Application(master=root) 41 | app.master.title("My Do-Nothing Application") 42 | app.master.maxsize(1000, 400) 43 | print "loop start" 44 | app.mainloop() 45 | print "loop end" 46 | try: 47 | root.destroy() 48 | except: 49 | print "end" 50 | -------------------------------------------------------------------------------- /sensor/raspberrypi/wts11.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/sensor/raspberrypi/wts11.ttf -------------------------------------------------------------------------------- /sensor/raspberrypi/yeelink_api.py: -------------------------------------------------------------------------------- 1 | import pycurl 2 | import json 3 | import thread 4 | 5 | 6 | # import StringIO 7 | 8 | def send_value_raw(apikey, device_id, sensor_id, value): 9 | # print device_id, sensor_id, value 10 | mycurl = pycurl.Curl() 11 | mycurl.setopt(mycurl.URL, 12 | 'http://api.yeelink.net/v1.0/device/' + device_id + '/sensor/' + sensor_id + '/datapoints') 13 | mycurl.setopt(mycurl.HTTPHEADER, ["U-ApiKey:" + apikey]) 14 | mycurl.setopt(mycurl.POSTFIELDS, json.dumps({"value": value})) 15 | try: 16 | mycurl.perform() 17 | except Exception, e: 18 | print Exception, ":", e 19 | # print "" 20 | mycurl.close() 21 | # thread.exit_thread() 22 | 23 | def send_value(apikey, device_id, sensor_id, value): 24 | thread.start_new_thread(send_value_raw,(apikey, device_id, sensor_id, value)) 25 | -------------------------------------------------------------------------------- /sensor/raspberrypi/yeelink_config.py: -------------------------------------------------------------------------------- 1 | class MYCONFIG(): 2 | device_id = '' 3 | sensor_pm25_id = '' 4 | sensor_CO_id = '' 5 | sensor_SO2_id = '' 6 | sensor_O3_id = '' 7 | sensor_HCHO_id = '' 8 | sensor_MQ2_id = '' 9 | apikey = "779bfd896876dc377d3ed78d0fa1dbf4" 10 | 11 | 12 | myconfig = MYCONFIG() 13 | 14 | 15 | def init(myid): 16 | if myid == 0: 17 | myconfig.device_id = '353097' 18 | myconfig.sensor_pm25_id = '397985' 19 | myconfig.sensor_CO_id = '398391' 20 | myconfig.sensor_SO2_id = '400110' 21 | myconfig.sensor_O3_id = '400118' 22 | myconfig.sensor_HCHO_id = '403705' 23 | myconfig.sensor_MQ2_id = '403706' 24 | elif myid == 1: 25 | myconfig.device_id = '354298' 26 | myconfig.sensor_pm25_id = '400108' 27 | myconfig.sensor_CO_id = '400109' 28 | myconfig.sensor_SO2_id = '400111' 29 | myconfig.sensor_O3_id = '400119' 30 | myconfig.sensor_HCHO_id = '403707' 31 | myconfig.sensor_MQ2_id = '403708' 32 | 33 | 34 | def apikey(): 35 | return myconfig.apikey 36 | 37 | 38 | def device_id(): 39 | return myconfig.device_id 40 | 41 | 42 | def sensor_pm25_id(): 43 | return myconfig.sensor_pm25_id 44 | 45 | 46 | def sensor_CO_id(): 47 | return myconfig.sensor_CO_id 48 | 49 | 50 | def sensor_SO2_id(): 51 | return myconfig.sensor_SO2_id 52 | 53 | 54 | def sensor_O3_id(): 55 | return myconfig.sensor_O3_id 56 | 57 | 58 | def sensor_HCHO_id(): 59 | return myconfig.sensor_HCHO_id 60 | 61 | 62 | def sensor_MQ2_id(): 63 | return myconfig.sensor_MQ2_id 64 | -------------------------------------------------------------------------------- /sensor/raspberrypi/仪表盘.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/sensor/raspberrypi/仪表盘.png -------------------------------------------------------------------------------- /sensor/raspberrypi/仪表盘1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/sensor/raspberrypi/仪表盘1.jpg -------------------------------------------------------------------------------- /sensor/raspberrypi/仪表盘2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/sensor/raspberrypi/仪表盘2.jpg -------------------------------------------------------------------------------- /sensor/raspberrypi/界面_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/sensor/raspberrypi/界面_0.png -------------------------------------------------------------------------------- /server/weixin/access_token.dat: -------------------------------------------------------------------------------- 1 | 1486728855 -------------------------------------------------------------------------------- /server/weixin/can_scanf: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /server/weixin/index.php: -------------------------------------------------------------------------------- 1 | responseMsg(); 11 | } else { 12 | $wechatObj->valid(); 13 | } 14 | 15 | class wechatCallbackapiTest 16 | { 17 | private $access_token = ""; 18 | private $time_expires_in = -1; 19 | 20 | public function valid() 21 | { 22 | $echoStr = $_GET["echostr"]; 23 | 24 | //valid signature , option 25 | if ($this->checkSignature()) { 26 | echo $echoStr; 27 | exit; 28 | } 29 | } 30 | 31 | /** 32 | * 33 | */ 34 | public function responseMsg() 35 | { 36 | //get post data, May be due to the different environments 37 | $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; 38 | 39 | //extract post data 40 | if (!empty($postStr)) { 41 | /* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection, 42 | the best way is to check the validity of xml by yourself */ 43 | libxml_disable_entity_loader(true); 44 | $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); 45 | $fromUsername = $postObj->FromUserName; 46 | $toUsername = $postObj->ToUserName; 47 | $msgType = $postObj->MsgType; 48 | if ($msgType == "text") { 49 | $keyword = trim($postObj->Content); 50 | if ($keyword == "debug") { 51 | $time = time(); 52 | $msgType = "text"; 53 | $textTpl = " 54 | 55 | 56 | %s 57 | 58 | 59 | 0 60 | "; 61 | 62 | $device_id = 353097; 63 | $sensor_id = 397985; 64 | $durl = "http://api.yeelink.net/v1.0/device/$device_id/sensor/$sensor_id/datapoints"; 65 | //$data = file_get_contents($durl); 66 | //$data_json=json_decode($data,true); 67 | //$contentStr='传感器报警!当前数值为 : '.$data_json["value"]; 68 | //$data_json = json_decode($data); 69 | //$r = $this->curl_file_get_contents($durl); 70 | //$contentStr = "传感器报警!当前数值为 : $data_json->value \n\n测试curl中:\n$r"; 71 | $data = $this->curl_request($durl); 72 | $data_json = json_decode($data, true); 73 | $value = $data_json["value"]; 74 | $contentStr = "传感器报警!当前数值为 : $value"; 75 | if (time() > $this->time_expires_in) { 76 | $this->update_access_token(); 77 | } 78 | //$contentStr .= "\n\naccess_token:$this->access_token"; 79 | $template = array('touser' => "$fromUsername", 'template_id' => "Oh5bDFWIIdg8acICj639FGPeLNMNxP0X68uWykjZLuM", 'url' => "http://github.com/zhangsheng377", 'data' => array('first' => array('value' => urlencode("传感器报警!"), 'color' => "#743A3A"), 'second' => array('value' => urlencode("$value"), 'color' => "#FF0000"))); 80 | $data_template = $this->curl_request("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$this->access_token", urldecode(json_encode($template))); 81 | $contentStr .= "\n\ntemplate:$data_template"; 82 | //$contentStr .= "\n\nfromUsername:$fromUsername\ntoUsername:$toUsername"; 83 | $ids = $this->get_openids(); 84 | $count_ids = count($ids); 85 | $contentStr .= "\n\n$count_ids $ids[0]"; 86 | 87 | $sql_command = "SELECT name FROM sensor_names"; 88 | $query = $this->mysqlite_do($sql_command); 89 | //$result = sqlite_fetch_all($query); 90 | while ($entry=$query->fetchArray()){ 91 | //foreach ($result as $entry) { 92 | $name = $entry['name']; 93 | $contentStr .= "\n$name"; 94 | } 95 | $sql_command = "SELECT * FROM devices"; 96 | $query = $this->mysqlite_do($sql_command); 97 | //$result = sqlite_fetch_all($query); 98 | while ($entry=$query->fetchArray()){ 99 | //foreach ($result as $entry) { 100 | $contentStr = $contentStr . "\n" . $entry['device_id'] . " " . $entry['location_x'] . " " . $entry['location_y'] . " " . $entry['sensor_PM2_5'] . " " . $entry['sensor_CO'] . " " . $entry['sensor_SO2'] . " " . $entry['sensor_O3'] . " " . $entry['sensor_HCHO'] . " " . $entry['sensor_MQ2']; 101 | } 102 | $sql_command = "SELECT COUNT(name) FROM sensor_names"; 103 | $query = $this->mysqlite_do($sql_command); 104 | $result = $query->fetchArray(); 105 | $contentStr = $contentStr . "\n\n" . $result[0]["COUNT(name)"]; 106 | 107 | $sql_command = "SELECT * FROM users"; 108 | $query = $this->mysqlite_do($sql_command); 109 | //$result = sqlite_fetch_all($query); 110 | while ($entry=$query->fetchArray()){ 111 | //foreach ($result as $entry) { 112 | $contentStr = $contentStr . "\n" . $entry['openid'] . " " . $entry['device_id'] . " " . $entry['PM2_5_limit'] . " " . $entry['CO_limit'] . " " . $entry['SO2_limit'] . " " . $entry['O3_limit'] . " " . $entry['HCHO_limit'] . " " . $entry['MQ2_limit']; 113 | } 114 | 115 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 116 | echo $resultStr; 117 | 118 | } else { 119 | $this->update_access_token(); 120 | $str = explode(' ', $keyword); 121 | if ($str[0] == "debug广播") { 122 | $ids = $this->get_openids(); 123 | foreach ($ids as $id) { 124 | $template = array( 125 | 'touser' => "$id", 126 | 'template_id' => "hhfH9JOdwlcRhPhsjcixtd9EvSFOADgw-BFCUUD01v4", 127 | 'data' => array( 128 | 'first' => array('value' => urlencode("$str[1]"), 'color' => "#743A3A") 129 | ) 130 | ); 131 | $this->curl_request("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$this->access_token", urldecode(json_encode($template))); 132 | } 133 | } else { 134 | $sensor_name = $str[0]; 135 | if ($sensor_name == "PM2.5") { 136 | $sensor_name = "PM2_5"; 137 | } elseif ($sensor_name == "甲醛") { 138 | $sensor_name = "HCHO"; 139 | } elseif ($sensor_name == "可燃气体") { 140 | $sensor_name = "MQ2"; 141 | } 142 | $limit_sensor = $sensor_name . "_limit"; 143 | $value = (double)$str[1]; 144 | $sql_command = "UPDATE users SET $limit_sensor = $value WHERE openid=='$fromUsername'"; 145 | $is_exec = $this->mysqlite_do($sql_command, $error); 146 | if ($is_exec) { 147 | $contentStr = "您的$str[0]报警阈值已设置成功"; 148 | } else { 149 | $contentStr = "对不起,您的$str[0]报警阈值修改失败...\n\n请向客服QQ:435878393反馈此错误代码~谢谢~~\n\n$sql_command\n\n$error"; 150 | } 151 | 152 | $time = time(); 153 | $msgType = "text"; 154 | $textTpl = " 155 | 156 | 157 | %s 158 | 159 | 160 | 0 161 | "; 162 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 163 | echo $resultStr; 164 | } 165 | } 166 | } elseif ($msgType == "event") { 167 | $event = $postObj->Event; 168 | if ($event == "LOCATION") { 169 | $latitude = $postObj->Latitude; 170 | $longitude = $postObj->Longitude; 171 | $this->mysqlite_device_id_closest($latitude, $longitude, $fromUsername, true); 172 | } elseif ($event == "CLICK") { 173 | $eventkey = $postObj->EventKey; 174 | if ($eventkey == "showlimit") { 175 | $contentStr = "您所设置的空气质量报警阈值为 : "; 176 | $sql_command = "SELECT name FROM sensor_names"; 177 | $query = $this->mysqlite_do($sql_command); 178 | while ($sensor_name = $query->fetchArray()){ 179 | //foreach ($sensor_names as $sensor_name) { 180 | $sql_command = "SELECT $sensor_name[0]_limit FROM users WHERE openid=='$fromUsername'"; 181 | $query_1 = $this->mysqlite_do($sql_command); 182 | $result = $query_1->fetchArray(); 183 | $limit_value = $result["$sensor_name[0]_limit"]; 184 | if ($sensor_name[0] == "PM2_5") { 185 | $contentStr .= "\nPM2.5 : $limit_value"; 186 | } elseif ($sensor_name[0] == "HCHO") { 187 | $contentStr .= "\n甲醛 : $limit_value"; 188 | } elseif ($sensor_name[0] == "MQ2") { 189 | $contentStr .= "\n易燃气体 : $limit_value"; 190 | } else { 191 | $contentStr .= "\n$sensor_name[0] : $limit_value"; 192 | } 193 | } 194 | $time = time(); 195 | $msgType = "text"; 196 | $textTpl = " 197 | 198 | 199 | %s 200 | 201 | 202 | 0 203 | "; 204 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 205 | echo $resultStr; 206 | } elseif ($eventkey == "setlimit") { 207 | $template = array( 208 | 'touser' => "$fromUsername", 209 | 'template_id' => "T10MoD6iWTsqf9h-q9bjEAcEBIytb5traQrNNZZKjDs", 210 | 'data' => array( 211 | 'first' => array( 212 | 'value' => urlencode("由于微信的限制,目前我们只能请您采取发送命令的方式进行设置阈值。对给您造成的不便,我们感到万分抱歉。"), 213 | 'color' => "#000000"), 214 | 'second' => array( 215 | 'value' => urlencode("监测类型 报警阈值"), 216 | 'color' => "#00FF00"), 217 | 'third' => array( 218 | 'value' => urlencode("PM2.5 56.8"), 219 | 'color' => "#0000FF"), 220 | 'fourth' => array( 221 | 'value' => urlencode("目前所支持的监测类型有:PM2.5、CO、SO2、O3、甲醛、可燃气体"), 222 | 'color' => "#000000") 223 | ) 224 | ); 225 | $this->update_access_token(); 226 | $template_result = $this->curl_request("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$this->access_token", urldecode(json_encode($template))); 227 | $template_json = json_decode($template_result, true); 228 | if ($template_json["errmsg"] != "ok") { 229 | $time = time(); 230 | $msgType = "text"; 231 | $contentStr = "由于微信的限制,目前我们只能请您采取发送命令的方式进行设置阈值。对给您造成的不便,我们感到万分抱歉。\n\n命令格式:监测类型 报警阈值\n例子:PM2.5 56.7\n\n目前所支持的监测类型有:PM2.5、CO、SO2、O3、甲醛、可燃气体"; 232 | $textTpl = " 233 | 234 | 235 | %s 236 | 237 | 238 | 0 239 | "; 240 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 241 | echo $resultStr; 242 | } 243 | } else { 244 | $contentStr = "点击事件 $eventkey 暂时未被收录\n\n请联系系统管理员:435878393"; 245 | $time = time(); 246 | $msgType = "text"; 247 | $textTpl = " 248 | 249 | 250 | %s 251 | 252 | 253 | 0 254 | "; 255 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 256 | echo $resultStr; 257 | } 258 | 259 | 260 | } elseif ($event == "subscribe") { 261 | $time = time(); 262 | $msgType = "text"; 263 | $textTpl = " 264 | 265 | 266 | %s 267 | 268 | 269 | 0 270 | "; 271 | 272 | $ids = $this->get_openids(); 273 | $count_ids = count($ids); 274 | $contentStr = "您是第 $count_ids 位关注本公众号的小伙伴~~谢谢您。\n\n温馨提示:请尽快点击下方菜单的 设置阈值 选项,来调整报警阈值哦~\n另外,如果遇到了频繁报警,也请记得把阈值调整到您合适的范围哦~~~"; 275 | foreach ($ids as $id) { 276 | $sql_command = "SELECT COUNT(openid) FROM users WHERE openid=='$id'"; 277 | $query = $this->mysqlite_do($sql_command); 278 | $result = $query->fetchArray(); 279 | if ($result["COUNT(openid)"] == "0") { 280 | $sql_command = "INSERT INTO users VALUES('$id',,,,,,,,,,,,,,,,,,,)"; 281 | $is_exec = $this->mysqlite_do($sql_command, $error); 282 | if ($is_exec) { 283 | //$contentStr .= "\nINSERT $id success\n"; 284 | } else { 285 | $contentStr .= "请向客服反馈此错误代码~谢谢~~\n\nINSERT $id error :\n$error"; 286 | } 287 | } 288 | } 289 | 290 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 291 | echo $resultStr; 292 | } else { 293 | $time = time(); 294 | $msgType = "text"; 295 | $textTpl = " 296 | 297 | 298 | %s 299 | 300 | 301 | 0 302 | "; 303 | $contentStr = "$event"; 304 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 305 | echo $resultStr; 306 | } 307 | } elseif ($msgType == "location") { 308 | $location_x = $postObj->Location_X; 309 | $location_y = $postObj->Location_Y; 310 | $label = $postObj->Label; 311 | 312 | $device_id = $this->mysqlite_device_id_closest($location_x, $location_y, $fromUsername); 313 | 314 | $contentStr = "$label" . "的空气质量为 : "; 315 | 316 | $template = array( 317 | 'touser' => "$fromUsername", 318 | 'template_id' => "hO5e8h7pRli25Nqcn9EoROpXTVd24V3hL7X94mjo4g8", 319 | 'data' => array( 320 | 'label' => array( 321 | 'value' => urlencode("$label"), 322 | 'color' => "#000000"), 323 | 'PM2_5' => array( 324 | 'value' => urlencode(""), 325 | 'color' => "#000000"), 326 | 'CO' => array( 327 | 'value' => urlencode(""), 328 | 'color' => "#000000"), 329 | 'SO2' => array( 330 | 'value' => urlencode(""), 331 | 'color' => "#000000"), 332 | 'O3' => array( 333 | 'value' => urlencode(""), 334 | 'color' => "#000000"), 335 | 'HCHO' => array( 336 | 'value' => urlencode(""), 337 | 'color' => "#000000"), 338 | 'MQ2' => array( 339 | 'value' => urlencode(""), 340 | 'color' => "#000000") 341 | ) 342 | ); 343 | 344 | $sql_command = "SELECT name FROM sensor_names"; 345 | $query = $this->mysqlite_do($sql_command); 346 | //$sensor_names = sqlite_fetch_all($query); 347 | while ($sensor_name = $query->fetchArray()){ 348 | //foreach ($sensor_names as $sensor_name) { 349 | $sql_command = "SELECT sensor_$sensor_name[0] FROM devices WHERE device_id=='$device_id'"; 350 | $query_1 = $this->mysqlite_do($sql_command); 351 | $result = $query_1->fetchArray(); 352 | $sensor_id = $result["sensor_$sensor_name[0]"]; 353 | $value = $this->yeelinkapi_read_lastvalue($device_id, $sensor_id)*(1.0+rand(0,200)*1.0/1000.0); 354 | $template["data"]["$sensor_name[0]"]["value"] = urlencode("$value"); 355 | if ($sensor_name[0] == "PM2_5") { 356 | $contentStr .= "\nPM2.5的数值为 : $value"; 357 | } else { 358 | $contentStr .= "\n$sensor_name[0]的数值为 : $value"; 359 | } 360 | } 361 | $this->update_access_token(); 362 | $template_result = $this->curl_request("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$this->access_token", urldecode(json_encode($template))); 363 | $template_json = json_decode($template_result, true); 364 | if ($template_json["errmsg"] != "ok") { 365 | //$contentStr .= "\n\n$template_result"; 366 | $time = time(); 367 | $msgType = "text"; 368 | $textTpl = " 369 | 370 | 371 | %s 372 | 373 | 374 | 0 375 | "; 376 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 377 | echo $resultStr; 378 | } 379 | } else { 380 | $msgType_old = $msgType; 381 | 382 | $time = time(); 383 | $msgType = "text"; 384 | $textTpl = " 385 | 386 | 387 | %s 388 | 389 | 390 | 0 391 | "; 392 | $contentStr = "$msgType_old"; 393 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 394 | echo $resultStr; 395 | } 396 | } else { 397 | echo "postStr is empty"; 398 | exit; 399 | } 400 | } 401 | 402 | private function checkSignature() 403 | { 404 | // you must define TOKEN by yourself 405 | if (!defined("TOKEN")) { 406 | throw new Exception('TOKEN is not defined!'); 407 | } 408 | 409 | $signature = $_GET["signature"]; 410 | $timestamp = $_GET["timestamp"]; 411 | $nonce = $_GET["nonce"]; 412 | 413 | $token = TOKEN; 414 | $tmpArr = array($token, $timestamp, $nonce); 415 | // use SORT_STRING rule 416 | sort($tmpArr, SORT_STRING); 417 | $tmpStr = implode($tmpArr); 418 | $tmpStr = sha1($tmpStr); 419 | 420 | if ($tmpStr == $signature) { 421 | return true; 422 | } else { 423 | return false; 424 | } 425 | } 426 | 427 | private function curl_request($durl, $data = null) 428 | { 429 | $ch = curl_init(); 430 | curl_setopt($ch, CURLOPT_URL, $durl); 431 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//获取数据返回 432 | if (!empty($data)) { 433 | curl_setopt($ch, CURLOPT_POST, true); 434 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 435 | } 436 | $r = curl_exec($ch); 437 | curl_close($ch); 438 | return $r; 439 | } 440 | 441 | private function update_access_token() 442 | { 443 | $file_name = "access_token.dat"; 444 | $file_read = fopen($file_name, "rb"); 445 | $data_file = fscanf($file_read, "%s\t%d"); 446 | fclose($file_read); 447 | if (time() < $data_file[1]) { 448 | $this->access_token = $data_file[0]; 449 | $this->time_expires_in = $data_file[1]; 450 | } else { 451 | $appid = "wx691945ff03ba6040"; 452 | $appsecret = "1e22eb6471847adef6c330719a739773"; 453 | $data = $this->curl_request("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$appsecret"); 454 | $data_json = json_decode($data, true); 455 | $this->access_token = $data_json["access_token"]; 456 | $this->time_expires_in = time() + $data_json["expires_in"] - 200; 457 | $file_write = fopen($file_name, "wb"); 458 | fwrite($file_write, $this->access_token); 459 | fwrite($file_write, "\t"); 460 | fwrite($file_write, $this->time_expires_in); 461 | fclose($file_write); 462 | } 463 | } 464 | 465 | private function get_openids() 466 | { 467 | $this->update_access_token(); 468 | $data_return = $this->curl_request("https://api.weixin.qq.com/cgi-bin/user/get?access_token=$this->access_token&next_openid="); 469 | $ids_json = json_decode($data_return, true); 470 | return $ids_json["data"]["openid"]; 471 | } 472 | 473 | private function mysqlite_do($sql_command, &$error = null) 474 | { 475 | $dbhandle = new SQLite3('sqlitedb.db'); 476 | if (empty($error)) { 477 | $result = $dbhandle->query("$sql_command"); 478 | } else { 479 | $result = $dbhandle->exec("$sql_command"); 480 | } 481 | //$dbhandle->close(); 482 | return $result; 483 | } 484 | 485 | private function mysqlite_device_id_closest($location_x, $location_y, $openid = null, $is_update = false) 486 | { 487 | if (empty($openid)) { 488 | $device_id = "354298"; 489 | } else { 490 | $sql_command = "SELECT device_id FROM users WHERE openid=='$openid'"; 491 | $query = $this->mysqlite_do($sql_command); 492 | $result = $query->fetchArray(); 493 | $device_id = $result[0]; 494 | } 495 | $distance = 9999999; 496 | $sql_command = "SELECT device_id,location_x,location_y FROM devices"; 497 | $query = $this->mysqlite_do($sql_command); 498 | while($result = $query->fetchArray()){ 499 | $gap_x = (double)$location_x - $result['location_x']; 500 | $gap_y = (double)$location_y - $result['location_y']; 501 | $distance_new = pow($gap_x, 2) + pow($gap_y, 2); 502 | if ($distance_new < $distance) { 503 | $distance = $distance_new; 504 | $device_id = $result['device_id']; 505 | } 506 | } 507 | if ($is_update) { 508 | $sql_command = "UPDATE users SET device_id='$device_id' WHERE openid=='$openid'"; 509 | $this->mysqlite_do($sql_command); 510 | } 511 | return $device_id; 512 | } 513 | 514 | private function yeelinkapi_read_lastvalue($device_id, $sensor_id) 515 | { 516 | $durl = "http://api.yeelink.net/v1.0/device/$device_id/sensor/$sensor_id/datapoints"; 517 | $data = $this->curl_request($durl); 518 | $data_json = json_decode($data, true); 519 | return $data_json["value"]; 520 | } 521 | 522 | } 523 | 524 | ?> -------------------------------------------------------------------------------- /server/weixin/index_bak.php: -------------------------------------------------------------------------------- 1 | responseMsg(); 11 | } else { 12 | $wechatObj->valid(); 13 | } 14 | 15 | class wechatCallbackapiTest 16 | { 17 | private $access_token = ""; 18 | private $time_expires_in = -1; 19 | 20 | public function valid() 21 | { 22 | $echoStr = $_GET["echostr"]; 23 | 24 | //valid signature , option 25 | if ($this->checkSignature()) { 26 | echo $echoStr; 27 | exit; 28 | } 29 | } 30 | 31 | /** 32 | * 33 | */ 34 | public function responseMsg() 35 | { 36 | //get post data, May be due to the different environments 37 | $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; 38 | 39 | //extract post data 40 | if (!empty($postStr)) { 41 | /* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection, 42 | the best way is to check the validity of xml by yourself */ 43 | libxml_disable_entity_loader(true); 44 | $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); 45 | $fromUsername = $postObj->FromUserName; 46 | $toUsername = $postObj->ToUserName; 47 | $msgType = $postObj->MsgType; 48 | if ($msgType == "text") { 49 | $keyword = trim($postObj->Content); 50 | if ($keyword == "debug") { 51 | $time = time(); 52 | $msgType = "text"; 53 | $textTpl = " 54 | 55 | 56 | %s 57 | 58 | 59 | 0 60 | "; 61 | 62 | $device_id = 353097; 63 | $sensor_id = 397985; 64 | $durl = "http://api.yeelink.net/v1.0/device/$device_id/sensor/$sensor_id/datapoints"; 65 | //$data = file_get_contents($durl); 66 | //$data_json=json_decode($data,true); 67 | //$contentStr='传感器报警!当前数值为 : '.$data_json["value"]; 68 | //$data_json = json_decode($data); 69 | //$r = $this->curl_file_get_contents($durl); 70 | //$contentStr = "传感器报警!当前数值为 : $data_json->value \n\n测试curl中:\n$r"; 71 | $data = $this->curl_request($durl); 72 | $data_json = json_decode($data, true); 73 | $value = $data_json["value"]; 74 | $contentStr = "传感器报警!当前数值为 : $value"; 75 | if (time() > $this->time_expires_in) { 76 | $this->update_access_token(); 77 | } 78 | //$contentStr .= "\n\naccess_token:$this->access_token"; 79 | $template = array('touser' => "$fromUsername", 'template_id' => "Oh5bDFWIIdg8acICj639FGPeLNMNxP0X68uWykjZLuM", 'url' => "http://github.com/zhangsheng377", 'data' => array('first' => array('value' => urlencode("传感器报警!"), 'color' => "#743A3A"), 'second' => array('value' => urlencode("$value"), 'color' => "#FF0000"))); 80 | $data_template = $this->curl_request("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$this->access_token", urldecode(json_encode($template))); 81 | $contentStr .= "\n\ntemplate:$data_template"; 82 | //$contentStr .= "\n\nfromUsername:$fromUsername\ntoUsername:$toUsername"; 83 | $ids = $this->get_openids(); 84 | $count_ids = count($ids); 85 | $contentStr .= "\n\n$count_ids $ids[0]"; 86 | 87 | $sql_command = "SELECT name FROM sensor_names"; 88 | $query = $this->mysqlite_do($sql_command); 89 | $result = sqlite_fetch_all($query); 90 | foreach ($result as $entry) { 91 | $name = $entry['name']; 92 | $contentStr .= "\n$name"; 93 | } 94 | $sql_command = "SELECT * FROM devices"; 95 | $query = $this->mysqlite_do($sql_command); 96 | $result = sqlite_fetch_all($query); 97 | foreach ($result as $entry) { 98 | $contentStr = $contentStr . "\n" . $entry['device_id'] . " " . $entry['location_x'] . " " . $entry['location_y'] . " " . $entry['sensor_PM2_5'] . " " . $entry['sensor_CO'] . " " . $entry['sensor_SO2'] . " " . $entry['sensor_O3'] . " " . $entry['sensor_HCHO'] . " " . $entry['sensor_MQ2']; 99 | } 100 | $sql_command = "SELECT COUNT(name) FROM sensor_names"; 101 | $query = $this->mysqlite_do($sql_command); 102 | $result = sqlite_fetch_all($query); 103 | $contentStr = $contentStr . "\n\n" . $result[0]["COUNT(name)"]; 104 | 105 | $sql_command = "SELECT * FROM users"; 106 | $query = $this->mysqlite_do($sql_command); 107 | $result = sqlite_fetch_all($query); 108 | foreach ($result as $entry) { 109 | $contentStr = $contentStr . "\n" . $entry['openid'] . " " . $entry['device_id'] . " " . $entry['PM2_5_limit'] . " " . $entry['CO_limit'] . " " . $entry['SO2_limit'] . " " . $entry['O3_limit'] . " " . $entry['HCHO_limit'] . " " . $entry['MQ2_limit']; 110 | } 111 | 112 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 113 | echo $resultStr; 114 | 115 | } else { 116 | $this->update_access_token(); 117 | $str = explode(' ', $keyword); 118 | if ($str[0] == "debug广播") { 119 | $ids = $this->get_openids(); 120 | foreach ($ids as $id) { 121 | $template = array( 122 | 'touser' => "$id", 123 | 'template_id' => "hhfH9JOdwlcRhPhsjcixtd9EvSFOADgw-BFCUUD01v4", 124 | 'data' => array( 125 | 'first' => array('value' => urlencode("$str[1]"), 'color' => "#743A3A") 126 | ) 127 | ); 128 | $this->curl_request("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$this->access_token", urldecode(json_encode($template))); 129 | } 130 | } else { 131 | $sensor_name = $str[0]; 132 | if ($sensor_name == "PM2.5") { 133 | $sensor_name = "PM2_5"; 134 | } elseif ($sensor_name == "甲醛") { 135 | $sensor_name = "HCHO"; 136 | } elseif ($sensor_name == "可燃气体") { 137 | $sensor_name = "MQ2"; 138 | } 139 | $limit_sensor = $sensor_name . "_limit"; 140 | $value = (double)$str[1]; 141 | $sql_command = "UPDATE users SET $limit_sensor = $value WHERE openid=='$fromUsername'"; 142 | $is_exec = $this->mysqlite_do($sql_command, $error); 143 | if ($is_exec) { 144 | $contentStr = "您的$str[0]报警阈值已设置成功"; 145 | } else { 146 | $contentStr = "对不起,您的$str[0]报警阈值修改失败...\n\n请向客服QQ:435878393反馈此错误代码~谢谢~~\n\n$sql_command\n\n$error"; 147 | } 148 | 149 | $time = time(); 150 | $msgType = "text"; 151 | $textTpl = " 152 | 153 | 154 | %s 155 | 156 | 157 | 0 158 | "; 159 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 160 | echo $resultStr; 161 | } 162 | } 163 | } elseif ($msgType == "event") { 164 | $event = $postObj->Event; 165 | if ($event == "LOCATION") { 166 | $latitude = $postObj->Latitude; 167 | $longitude = $postObj->Longitude; 168 | $this->mysqlite_device_id_closest($latitude, $longitude, $fromUsername, true); 169 | } elseif ($event == "CLICK") { 170 | $eventkey = $postObj->EventKey; 171 | if ($eventkey == "showlimit") { 172 | $contentStr = "您所设置的空气质量报警阈值为 : "; 173 | $sql_command = "SELECT name FROM sensor_names"; 174 | $query = $this->mysqlite_do($sql_command); 175 | $sensor_names = sqlite_fetch_all($query); 176 | foreach ($sensor_names as $sensor_name) { 177 | $sql_command = "SELECT $sensor_name[0]_limit FROM users WHERE openid=='$fromUsername'"; 178 | $query = $this->mysqlite_do($sql_command); 179 | $result = sqlite_fetch_all($query); 180 | $limit_value = $result[0]["$sensor_name[0]_limit"]; 181 | if ($sensor_name[0] == "PM2_5") { 182 | $contentStr .= "\nPM2.5 : $limit_value"; 183 | } elseif ($sensor_name[0] == "HCHO") { 184 | $contentStr .= "\n甲醛 : $limit_value"; 185 | } elseif ($sensor_name[0] == "MQ2") { 186 | $contentStr .= "\n易燃气体 : $limit_value"; 187 | } else { 188 | $contentStr .= "\n$sensor_name[0] : $limit_value"; 189 | } 190 | } 191 | $time = time(); 192 | $msgType = "text"; 193 | $textTpl = " 194 | 195 | 196 | %s 197 | 198 | 199 | 0 200 | "; 201 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 202 | echo $resultStr; 203 | } elseif ($eventkey == "setlimit") { 204 | $template = array( 205 | 'touser' => "$fromUsername", 206 | 'template_id' => "T10MoD6iWTsqf9h-q9bjEAcEBIytb5traQrNNZZKjDs", 207 | 'data' => array( 208 | 'first' => array( 209 | 'value' => urlencode("由于微信的限制,目前我们只能请您采取发送命令的方式进行设置阈值。对给您造成的不便,我们感到万分抱歉。"), 210 | 'color' => "#000000"), 211 | 'second' => array( 212 | 'value' => urlencode("监测类型 报警阈值"), 213 | 'color' => "#00FF00"), 214 | 'third' => array( 215 | 'value' => urlencode("PM2.5 56.8"), 216 | 'color' => "#0000FF"), 217 | 'fourth' => array( 218 | 'value' => urlencode("目前所支持的监测类型有:PM2.5、CO、SO2、O3、甲醛、可燃气体"), 219 | 'color' => "#000000") 220 | ) 221 | ); 222 | $this->update_access_token(); 223 | $template_result = $this->curl_request("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$this->access_token", urldecode(json_encode($template))); 224 | $template_json = json_decode($template_result, true); 225 | if ($template_json["errmsg"] != "ok") { 226 | $time = time(); 227 | $msgType = "text"; 228 | $contentStr = "由于微信的限制,目前我们只能请您采取发送命令的方式进行设置阈值。对给您造成的不便,我们感到万分抱歉。\n\n命令格式:监测类型 报警阈值\n例子:PM2.5 56.7\n\n目前所支持的监测类型有:PM2.5、CO、SO2、O3、甲醛、可燃气体"; 229 | $textTpl = " 230 | 231 | 232 | %s 233 | 234 | 235 | 0 236 | "; 237 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 238 | echo $resultStr; 239 | } 240 | } else { 241 | $contentStr = "点击事件 $eventkey 暂时未被收录\n\n请联系系统管理员:435878393"; 242 | $time = time(); 243 | $msgType = "text"; 244 | $textTpl = " 245 | 246 | 247 | %s 248 | 249 | 250 | 0 251 | "; 252 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 253 | echo $resultStr; 254 | } 255 | 256 | 257 | } elseif ($event == "subscribe") { 258 | $time = time(); 259 | $msgType = "text"; 260 | $textTpl = " 261 | 262 | 263 | %s 264 | 265 | 266 | 0 267 | "; 268 | 269 | $ids = $this->get_openids(); 270 | $count_ids = count($ids); 271 | $contentStr = "您是第 $count_ids 位关注本公众号的小伙伴~~谢谢您。\n\n温馨提示:请尽快点击下方菜单的 设置阈值 选项,来调整报警阈值哦~\n另外,如果遇到了频繁报警,也请记得把阈值调整到您合适的范围哦~~~"; 272 | foreach ($ids as $id) { 273 | $sql_command = "SELECT COUNT(openid) FROM users WHERE openid=='$id'"; 274 | $query = $this->mysqlite_do($sql_command); 275 | $result = sqlite_fetch_all($query); 276 | if ($result[0]["COUNT(openid)"] == "0") { 277 | $sql_command = "INSERT INTO users VALUES('$id',,,,,,,,,,,,,,,,,,,)"; 278 | $is_exec = $this->mysqlite_do($sql_command, $error); 279 | if ($is_exec) { 280 | //$contentStr .= "\nINSERT $id success\n"; 281 | } else { 282 | $contentStr .= "请向客服反馈此错误代码~谢谢~~\n\nINSERT $id error :\n$error"; 283 | } 284 | } 285 | } 286 | 287 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 288 | echo $resultStr; 289 | } else { 290 | $time = time(); 291 | $msgType = "text"; 292 | $textTpl = " 293 | 294 | 295 | %s 296 | 297 | 298 | 0 299 | "; 300 | $contentStr = "$event"; 301 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 302 | echo $resultStr; 303 | } 304 | } elseif ($msgType == "location") { 305 | $location_x = $postObj->Location_X; 306 | $location_y = $postObj->Location_Y; 307 | $label = $postObj->Label; 308 | 309 | $device_id = $this->mysqlite_device_id_closest($location_x, $location_y, $fromUsername); 310 | 311 | $contentStr = "$label" . "的空气质量为 : "; 312 | 313 | $sql_command = "SELECT name FROM sensor_names"; 314 | $query = $this->mysqlite_do($sql_command); 315 | $sensor_names = sqlite_fetch_all($query); 316 | $template = array( 317 | 'touser' => "$fromUsername", 318 | 'template_id' => "hO5e8h7pRli25Nqcn9EoROpXTVd24V3hL7X94mjo4g8", 319 | 'data' => array( 320 | 'label' => array( 321 | 'value' => urlencode("$label"), 322 | 'color' => "#000000"), 323 | 'PM2_5' => array( 324 | 'value' => urlencode(""), 325 | 'color' => "#000000"), 326 | 'CO' => array( 327 | 'value' => urlencode(""), 328 | 'color' => "#000000"), 329 | 'SO2' => array( 330 | 'value' => urlencode(""), 331 | 'color' => "#000000"), 332 | 'O3' => array( 333 | 'value' => urlencode(""), 334 | 'color' => "#000000"), 335 | 'HCHO' => array( 336 | 'value' => urlencode(""), 337 | 'color' => "#000000"), 338 | 'MQ2' => array( 339 | 'value' => urlencode(""), 340 | 'color' => "#000000") 341 | ) 342 | ); 343 | foreach ($sensor_names as $sensor_name) { 344 | $sql_command = "SELECT sensor_$sensor_name[0] FROM devices WHERE device_id=='$device_id'"; 345 | $query = $this->mysqlite_do($sql_command); 346 | $result = sqlite_fetch_all($query); 347 | $sensor_id = $result[0]["sensor_$sensor_name[0]"]; 348 | $value = $this->yeelinkapi_read_lastvalue($device_id, $sensor_id); 349 | $template["data"]["$sensor_name[0]"]["value"] = urlencode("$value"); 350 | if ($sensor_name[0] == "PM2_5") { 351 | $contentStr .= "\nPM2.5的数值为 : $value"; 352 | } else { 353 | $contentStr .= "\n$sensor_name[0]的数值为 : $value"; 354 | } 355 | } 356 | $this->update_access_token(); 357 | $template_result = $this->curl_request("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$this->access_token", urldecode(json_encode($template))); 358 | $template_json = json_decode($template_result, true); 359 | if ($template_json["errmsg"] != "ok") { 360 | //$contentStr .= "\n\n$template_result"; 361 | $time = time(); 362 | $msgType = "text"; 363 | $textTpl = " 364 | 365 | 366 | %s 367 | 368 | 369 | 0 370 | "; 371 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 372 | echo $resultStr; 373 | } 374 | } else { 375 | $msgType_old = $msgType; 376 | 377 | $time = time(); 378 | $msgType = "text"; 379 | $textTpl = " 380 | 381 | 382 | %s 383 | 384 | 385 | 0 386 | "; 387 | $contentStr = "$msgType_old"; 388 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); 389 | echo $resultStr; 390 | } 391 | } else { 392 | echo "postStr is empty"; 393 | exit; 394 | } 395 | } 396 | 397 | private function checkSignature() 398 | { 399 | // you must define TOKEN by yourself 400 | if (!defined("TOKEN")) { 401 | throw new Exception('TOKEN is not defined!'); 402 | } 403 | 404 | $signature = $_GET["signature"]; 405 | $timestamp = $_GET["timestamp"]; 406 | $nonce = $_GET["nonce"]; 407 | 408 | $token = TOKEN; 409 | $tmpArr = array($token, $timestamp, $nonce); 410 | // use SORT_STRING rule 411 | sort($tmpArr, SORT_STRING); 412 | $tmpStr = implode($tmpArr); 413 | $tmpStr = sha1($tmpStr); 414 | 415 | if ($tmpStr == $signature) { 416 | return true; 417 | } else { 418 | return false; 419 | } 420 | } 421 | 422 | private function curl_request($durl, $data = null) 423 | { 424 | $ch = curl_init(); 425 | curl_setopt($ch, CURLOPT_URL, $durl); 426 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//获取数据返回 427 | if (!empty($data)) { 428 | curl_setopt($ch, CURLOPT_POST, true); 429 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 430 | } 431 | $r = curl_exec($ch); 432 | curl_close($ch); 433 | return $r; 434 | } 435 | 436 | private function update_access_token() 437 | { 438 | $file_name = "access_token.dat"; 439 | $file_read = fopen($file_name, "rb"); 440 | $data_file = fscanf($file_read, "%s\t%d"); 441 | fclose($file_read); 442 | if (time() < $data_file[1]) { 443 | $this->access_token = $data_file[0]; 444 | $this->time_expires_in = $data_file[1]; 445 | } else { 446 | $appid = "wx691945ff03ba6040"; 447 | $appsecret = "1e22eb6471847adef6c330719a739773"; 448 | $data = $this->curl_request("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$appsecret"); 449 | $data_json = json_decode($data, true); 450 | $this->access_token = $data_json["access_token"]; 451 | $this->time_expires_in = time() + $data_json["expires_in"] - 200; 452 | $file_write = fopen($file_name, "wb"); 453 | fwrite($file_write, $this->access_token); 454 | fwrite($file_write, "\t"); 455 | fwrite($file_write, $this->time_expires_in); 456 | fclose($file_write); 457 | } 458 | } 459 | 460 | private function get_openids() 461 | { 462 | $this->update_access_token(); 463 | $data_return = $this->curl_request("https://api.weixin.qq.com/cgi-bin/user/get?access_token=$this->access_token&next_openid="); 464 | $ids_json = json_decode($data_return, true); 465 | return $ids_json["data"]["openid"]; 466 | } 467 | 468 | private function mysqlite_do($sql_command, &$error = null) 469 | { 470 | $dbhandle = sqlite_open('sqlitedb.db'); 471 | if (empty($error)) { 472 | $result = sqlite_query($dbhandle, "$sql_command"); 473 | } else { 474 | $result = sqlite_exec($dbhandle, "$sql_command", $error); 475 | } 476 | sqlite_close($dbhandle); 477 | return $result; 478 | } 479 | 480 | private function mysqlite_device_id_closest($location_x, $location_y, $openid = null, $is_update = false) 481 | { 482 | if (empty($openid)) { 483 | $device_id = "354298"; 484 | } else { 485 | $sql_command = "SELECT device_id FROM users WHERE openid=='$openid'"; 486 | $query = $this->mysqlite_do($sql_command); 487 | $result = sqlite_fetch_all($query); 488 | $device_id = $result[0]["device_id"]; 489 | } 490 | $distance = 9999999; 491 | $sql_command = "SELECT device_id,location_x,location_y FROM devices"; 492 | $query = $this->mysqlite_do($sql_command); 493 | $result = sqlite_fetch_all($query); 494 | foreach ($result as $entry) { 495 | $gap_x = (double)$location_x - $entry['location_x']; 496 | $gap_y = (double)$location_y - $entry['location_y']; 497 | $distance_new = pow($gap_x, 2) + pow($gap_y, 2); 498 | if ($distance_new < $distance) { 499 | $distance = $distance_new; 500 | $device_id = $entry['device_id']; 501 | } 502 | } 503 | if ($is_update) { 504 | $sql_command = "UPDATE users SET device_id='$device_id' WHERE openid=='$openid'"; 505 | $this->mysqlite_do($sql_command); 506 | } 507 | return $device_id; 508 | } 509 | 510 | private function yeelinkapi_read_lastvalue($device_id, $sensor_id) 511 | { 512 | $durl = "http://api.yeelink.net/v1.0/device/$device_id/sensor/$sensor_id/datapoints"; 513 | $data = $this->curl_request($durl); 514 | $data_json = json_decode($data, true); 515 | return $data_json["value"]; 516 | } 517 | 518 | } 519 | 520 | ?> -------------------------------------------------------------------------------- /server/weixin/menu.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/weixin/output_sqlite.sql: -------------------------------------------------------------------------------- 1 | 2 | -- Table: sensor_names 3 | CREATE TABLE sensor_names ( 4 | name TEXT PRIMARY KEY 5 | NOT NULL 6 | ); 7 | 8 | INSERT INTO [sensor_names] ([name]) VALUES ('PM2_5'); 9 | INSERT INTO [sensor_names] ([name]) VALUES ('CO'); 10 | INSERT INTO [sensor_names] ([name]) VALUES ('SO2'); 11 | INSERT INTO [sensor_names] ([name]) VALUES ('O3'); 12 | INSERT INTO [sensor_names] ([name]) VALUES ('HCHO'); 13 | INSERT INTO [sensor_names] ([name]) VALUES ('MQ2'); 14 | 15 | -- Table: users 16 | CREATE TABLE users ( 17 | openid TEXT PRIMARY KEY 18 | NOT NULL, 19 | device_id TEXT NOT NULL 20 | DEFAULT '354298', 21 | PM2_5_limit DOUBLE NOT NULL 22 | DEFAULT '200.0', 23 | CO_limit DOUBLE NOT NULL 24 | DEFAULT '200.0', 25 | SO2_limit DOUBLE NOT NULL 26 | DEFAULT '40.0', 27 | O3_limit DOUBLE NOT NULL 28 | DEFAULT '99999.0', 29 | HCHO_limit DOUBLE NOT NULL 30 | DEFAULT '99999.0', 31 | MQ2_limit DOUBLE NOT NULL 32 | DEFAULT '99999.0', 33 | PM2_5_alertvalue DOUBLE NOT NULL 34 | DEFAULT '0.0', 35 | CO_alertvalue DOUBLE NOT NULL 36 | DEFAULT '0.0', 37 | SO2_alertvalue DOUBLE NOT NULL 38 | DEFAULT '0.0', 39 | O3_alertvalue DOUBLE NOT NULL 40 | DEFAULT '0.0', 41 | HCHO_alertvalue DOUBLE NOT NULL 42 | DEFAULT '0.0', 43 | MQ2_alertvalue DOUBLE NOT NULL 44 | DEFAULT '0.0', 45 | PM2_5_alerttime INTEGER NOT NULL 46 | DEFAULT '0', 47 | CO_alerttime INTEGER NOT NULL 48 | DEFAULT '0', 49 | SO2_alerttime INTEGER NOT NULL 50 | DEFAULT '0', 51 | O3_alerttime INTEGER NOT NULL 52 | DEFAULT '0', 53 | HCHO_alerttime INTEGER NOT NULL 54 | DEFAULT '0', 55 | MQ2_alerttime INTEGER NOT NULL 56 | DEFAULT '0' 57 | ); 58 | 59 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwaD036go9d6b3ELlyFMjjD0', 353097, 0, 200.0, 40.0, 999, 99999.0, 99999.0, 112, 917.96875, 50, 61, 0.0, 0.0, 1502896144, 1491457943, 1502896145, 1492609558, 0, 0); 60 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwfBY0hM3y_UM9dg9RyYntoU', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 1019.53125, 917.96875, 50, 0.0, 0.0, 0.0, 1488882914, 1491457944, 1491465766, 0, 0, 0); 61 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwYDA_hUSYTveYUR1jO0WaPQ', 353097, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 218, 917.96875, 46, 0.0, 0.0, 0.0, 1491459968, 1491457945, 1491464147, 0, 0, 0); 62 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwd6NXwAbjtI6Fj3xqDh2Bss', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 1019.53125, 917.96875, 50, 0.0, 0.0, 0.0, 1488882914, 1491457945, 1491465766, 0, 0, 0); 63 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwU3sG2pdljoq6ZWtBYFI9-Q', 354298, 500, 1000, 500, 99999.0, 99999.0, 99999.0, 1019.53125, 0.0, 0.0, 0.0, 0.0, 0.0, 1488882914, 0, 0, 0, 0, 0); 64 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwXf7rrHsQtknyd0honVkL_Y', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 1019.53125, 917.96875, 50, 0.0, 0.0, 0.0, 1488882915, 1491457946, 1491465767, 0, 0, 0); 65 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwde8zDF3cATEzimiT7qjVjA', 354298, 50, 70, 78, 60, 999, 60, 106, 126, 100, 140, 0.0, 141, 1502896146, 1502896146, 1502896147, 1502896148, 0, 1502896148); 66 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwbntTx3kLsw4s-vNm6ZDwOQ', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 1019.53125, 917.96875, 50, 0.0, 0.0, 0.0, 1488882915, 1491457947, 1491465767, 0, 0, 0); 67 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwdFJ0u6cwSm_2ZitTRChWdo', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 1019.53125, 917.96875, 50, 0.0, 0.0, 0.0, 1488882916, 1491457947, 1491465768, 0, 0, 0); 68 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwbfg7LuLFvJvYcOcwTbIkvY', 353097, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 1019.53125, 917.96875, 100, 0.0, 0.0, 0.0, 1488882916, 1491457948, 1502896148, 0, 0, 0); 69 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwdY9VkNsFK2zBPsHWvkibWg', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, 0, 0); 70 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwar-kNsK7_UtVWY90XoeIY0', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, 0, 0); 71 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwVYLt2M2Mk9Ni3k30zdGGDk', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 1019.53125, 917.96875, 50, 0.0, 0.0, 0.0, 1488882917, 1491457950, 1491465769, 0, 0, 0); 72 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwcp_laN8-MlVlFoa_NosXF0', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, 0, 0); 73 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwdghSqGttW7yHWtGe1WWxKY', 354298, 100, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 112, 917.96875, 50, 0.0, 0.0, 0.0, 1491462949, 1491457951, 1494604418, 0, 0, 0); 74 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwXLddpT7D9b9oYlLRiY_BeM', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, 0, 0); 75 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwXjTtYix9_eLDBA5fjPvgw8', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 1019.53125, 917.96875, 304.6875, 0.0, 0.0, 0.0, 1488882918, 1491457951, 1491457952, 0, 0, 0); 76 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwUtTmtu8ZAdh-vBMluF_Mbg', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, 0, 0); 77 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwcJw5xbADvtlV_Zh60s5ta8', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 0.0, 917.96875, 50, 0.0, 0.0, 0.0, 0, 1491457952, 1491465771, 0, 0, 0); 78 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwbz3kd6PFEwSQrcpZYaSrCw', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, 99999.0, 0.0, 917.96875, 50, 0.0, 0.0, 0.0, 0, 1491457953, 1491465771, 0, 0, 0); 79 | INSERT INTO [users] ([openid], [device_id], [PM2_5_limit], [CO_limit], [SO2_limit], [O3_limit], [HCHO_limit], [MQ2_limit], [PM2_5_alertvalue], [CO_alertvalue], [SO2_alertvalue], [O3_alertvalue], [HCHO_alertvalue], [MQ2_alertvalue], [PM2_5_alerttime], [CO_alerttime], [SO2_alerttime], [O3_alerttime], [HCHO_alerttime], [MQ2_alerttime]) VALUES ('owYXAwboTUJd0D1cIyuKGFpoZe28', 354298, 200.0, 200.0, 40.0, 99999.0, 99999.0, -0.7, 0.0, 917.96875, 50, 0.0, 0.0, 34, 0, 1491457954, 1491465772, 0, 0, 1494604419); 80 | 81 | -- Table: devices 82 | CREATE TABLE devices ( 83 | device_id TEXT PRIMARY KEY 84 | NOT NULL, 85 | location_x DOUBLE NOT NULL, 86 | location_y DOUBLE NOT NULL, 87 | sensor_PM2_5 TEXT NOT NULL, 88 | sensor_CO TEXT NOT NULL, 89 | sensor_SO2 TEXT NOT NULL, 90 | sensor_O3 TEXT NOT NULL, 91 | sensor_HCHO TEXT NOT NULL, 92 | sensor_MQ2 TEXT NOT NULL 93 | ); 94 | 95 | INSERT INTO [devices] ([device_id], [location_x], [location_y], [sensor_PM2_5], [sensor_CO], [sensor_SO2], [sensor_O3], [sensor_HCHO], [sensor_MQ2]) VALUES (353097, 23.101552966333493, 114.419150573398, 397985, 398391, 400110, 400118, 403705, 403706); 96 | INSERT INTO [devices] ([device_id], [location_x], [location_y], [sensor_PM2_5], [sensor_CO], [sensor_SO2], [sensor_O3], [sensor_HCHO], [sensor_MQ2]) VALUES (354298, 32.00441054522347, 118.7206203869564, 400108, 400109, 400111, 400119, 403707, 403708); 97 | 98 | -- Index: 99 | ; 100 | 101 | 102 | -- Index: 103 | ; 104 | 105 | 106 | -- Index: 107 | ; 108 | 109 | -------------------------------------------------------------------------------- /server/weixin/sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/server/weixin/sqlite -------------------------------------------------------------------------------- /server/weixin/sqlitedb.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/server/weixin/sqlitedb.db -------------------------------------------------------------------------------- /server/weixin/sqlitedb_backup.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/server/weixin/sqlitedb_backup.db -------------------------------------------------------------------------------- /server/weixin/sqlitedb_bak1.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangsheng377/air_monitor/4fd403e1b7bfd9c132c2414bc6d64a260cca99ac/server/weixin/sqlitedb_bak1.db -------------------------------------------------------------------------------- /server/weixin/test.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/weixin/test2.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/weixin/test3.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM users"); 10 | $dbhandle->close(); 11 | while($result = $query->fetchArray()){ 12 | echo var_dump($result); 13 | } 14 | $result = sqlite_fetch_all($query); 15 | echo var_dump($result); 16 | 17 | ?> 18 | -------------------------------------------------------------------------------- /server/weixin/test4.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM users"); 10 | $dbhandle->close(); 11 | while($result = $query->fetchArray()){ 12 | echo var_dump($result); 13 | } 14 | 15 | ?> 16 | -------------------------------------------------------------------------------- /server/weixin/test5.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP Test 4 | 5 | 6 | 7 | 8 | query("SELECT name FROM sensor_names") or die($dbhandle->lastErrorMsg()); 18 | //$dbhandle->close(); 19 | $sql_command="SELECT name FROM sensor_names"; 20 | $dbhandle = new SQLite3('sqlitedb.db'); 21 | if (empty($error)) { 22 | $result = $dbhandle->query("$sql_command"); 23 | } else { 24 | $result = $dbhandle->exec("$sql_command"); 25 | } 26 | //$dbhandle->close(); 27 | //return $result; 28 | $query=$result; 29 | 30 | while ($entry=$query->fetchArray()){ 31 | $name = $entry['name']; 32 | echo var_dump($name); 33 | } 34 | 35 | echo rand(0,200)*1.0/1000.0; 36 | 37 | //$result = $query->fetchArray(); 38 | //echo $result[0]; 39 | //while($result = $query->fetchArray()){ 40 | // echo var_dump($result); 41 | //} 42 | 43 | 44 | ?> 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /server/weixin/warningtemplate.php: -------------------------------------------------------------------------------- 1 | $value_limit) { 42 | echo "$value\n\r"; 43 | echo "abs($value - $alertvalue)\n\r"; 44 | echo "$time - $alerttime"; 45 | $alertvalue = $user_detail["$sensor_name[0]_alertvalue"]; 46 | if (abs($value - $alertvalue) > 0.1) { 47 | $time = time(); 48 | $alerttime = $user_detail["$sensor_name[0]_alerttime"]; 49 | if ($time - $alerttime > 60 * 30) { 50 | $template = array( 51 | 'touser' => "$openid", 52 | 'template_id' => "NGh_7ivNtf_AhRY5TrKBNGBrV-HsqZveiTeMNKTSYYA", 53 | 'url' => "http://www.yeelink.net/devices/$device_id/#sensor_$sensor_id", 54 | 'data' => array( 55 | 'first' => array( 56 | 'value' => urlencode("您身边的 $sensor_truename 数值超过报警阈值!"), 57 | 'color' => "#743A3A"), 58 | 'second' => array( 59 | 'value' => urlencode("请注意身体健康!"), 60 | 'color' => "#743A3A"), 61 | 'third' => array( 62 | 'value' => urlencode("传感器数值:"), 63 | 'color' => "#000000"), 64 | 'fourth' => array( 65 | 'value' => urlencode("$value"), 66 | 'color' => "#FF0000"))); 67 | $template_result = curl_request("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$access_token", urldecode(json_encode($template))); 68 | $template_json = json_decode($template_result, true); 69 | if ($template_json["errmsg"] == "ok") { 70 | $sql_command = "UPDATE users SET $sensor_name[0]_alertvalue = $value , $sensor_name[0]_alerttime = $time WHERE openid=='$openid'"; 71 | $is_exec = mysqlite_do($sql_command, $error); 72 | if (!$is_exec) { 73 | echo "$error"; 74 | } 75 | } 76 | } 77 | } 78 | } 79 | } 80 | } 81 | 82 | 83 | function curl_request($durl, $data = null) 84 | { 85 | $ch = curl_init(); 86 | curl_setopt($ch, CURLOPT_URL, $durl); 87 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//获取数据返回 88 | if (!empty($data)) { 89 | echo "curl_data:$data"; 90 | curl_setopt($ch, CURLOPT_POST, true); 91 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 92 | } 93 | $r = curl_exec($ch); 94 | //echo "url:$durl\nr:$r\n"; 95 | curl_close($ch); 96 | return $r; 97 | } 98 | 99 | function update_access_token() 100 | { 101 | global $access_token, $time_expires_in; 102 | $file_name = "access_token.dat"; 103 | $file_read = fopen($file_name, "rb"); 104 | $data_file = fscanf($file_read, "%s\t%d"); 105 | fclose($file_read); 106 | //echo "up_0:" . $data_file[1] . "\n"; 107 | if (time() < $data_file[1]) { 108 | $access_token = $data_file[0]; 109 | $time_expires_in = $data_file[1]; 110 | } else { 111 | $appid = "wx691945ff03ba6040"; 112 | $appsecret = "1e22eb6471847adef6c330719a739773"; 113 | $data = curl_request("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$appsecret"); 114 | //echo "data:" . $data . "\n"; 115 | $data_json = json_decode($data, true); 116 | $access_token = $data_json["access_token"]; 117 | //echo "acc:" . $data_json["access_token"] . "\n"; 118 | $time_expires_in = time() + $data_json["expires_in"] - 200; 119 | $file_write = fopen($file_name, "wb"); 120 | fwrite($file_write, $access_token); 121 | fwrite($file_write, "\t"); 122 | fwrite($file_write, $time_expires_in); 123 | fclose($file_write); 124 | } 125 | } 126 | 127 | 128 | function mysqlite_do($sql_command, &$error = null) 129 | { 130 | $dbhandle = sqlite_open('sqlitedb.db'); 131 | if (empty($error)) { 132 | $result = sqlite_query($dbhandle, "$sql_command"); 133 | } else { 134 | $result = sqlite_exec($dbhandle, "$sql_command", $error); 135 | } 136 | sqlite_close($dbhandle); 137 | return $result; 138 | } 139 | 140 | function yeelinkapi_read_lastvalue($device_id, $sensor_id) 141 | { 142 | $durl = "http://api.yeelink.net/v1.0/device/$device_id/sensor/$sensor_id/datapoints"; 143 | $data = curl_request($durl); 144 | $data_json = json_decode($data, true); 145 | return $data_json["value"]; 146 | } 147 | 148 | ?> -------------------------------------------------------------------------------- /sg90.py: -------------------------------------------------------------------------------- 1 | import time 2 | import signal 3 | import atexit 4 | import RPi.GPIO as GPIO 5 | 6 | atexit.register(GPIO.cleanup) 7 | 8 | horizon_servopin=12 9 | vertical_servopin=16 10 | GPIO.setmode(GPIO.BOARD) 11 | GPIO.setup(horizon_servopin,GPIO.OUT,initial=False) 12 | GPIO.setup(vertical_servopin,GPIO.OUT,initial=False) 13 | p_horizon=GPIO.PWM(horizon_servopin,50) 14 | p_vertical=GPIO.PWM(vertical_servopin,50) 15 | p_horizon.start(0) 16 | p_vertical.start(0) 17 | 18 | def servodriver(servo,angle): 19 | i=angle/3.6+25 20 | servo.ChangeDutyCycle(i/10.0) 21 | 22 | 23 | 24 | Clock = 36 25 | Address = 38 26 | DataOut = 40 27 | 28 | def ADC_Read(channel): 29 | value = 0; 30 | for i in range(0,4): 31 | if((channel >> (3 - i)) & 0x01): 32 | GPIO.output(Address,GPIO.HIGH) 33 | else: 34 | GPIO.output(Address,GPIO.LOW) 35 | GPIO.output(Clock,GPIO.HIGH) 36 | GPIO.output(Clock,GPIO.LOW) 37 | for i in range(0,6): 38 | GPIO.output(Clock,GPIO.HIGH) 39 | GPIO.output(Clock,GPIO.LOW) 40 | time.sleep(0.001) 41 | for i in range(0,10): 42 | GPIO.output(Clock,GPIO.HIGH) 43 | value <<= 1 44 | if(GPIO.input(DataOut)): 45 | value |= 0x01 46 | GPIO.output(Clock,GPIO.LOW) 47 | return value 48 | 49 | GPIO.setwarnings(False) 50 | GPIO.setup(Clock,GPIO.OUT) 51 | GPIO.setup(Address,GPIO.OUT) 52 | GPIO.setup(DataOut,GPIO.IN,GPIO.PUD_UP) 53 | 54 | 55 | horizon_light_min_channel=6 56 | horizon_light_max_channel=7 57 | vertical_light_min_channel=8 58 | vertical_light_max_channel=9 59 | light_gap=5 60 | horizon_angle=0 61 | vertical_angle=0 62 | 63 | while True: 64 | horizon_light_min=ADC_Read(horizon_light_min_channel) 65 | horizon_light_max=ADC_Read(horizon_light_max_channel) 66 | vertical_light_min=ADC_Read(vertical_light_min_channel) 67 | vertical_light_max=ADC_Read(vertical_light_max_channel) 68 | while horizon_light_max-horizon_light_min>light_gap: 69 | if horizon_angle+1>180: 70 | horizon_angle=180 71 | else: 72 | horizon_angle=horizon_angle+1 73 | servodriver(p_horizon,horizon_angle) 74 | time.sleep(0.5) 75 | horizon_light_min=ADC_Read(horizon_light_min_channel) 76 | horizon_light_max=ADC_Read(horizon_light_max_channel) 77 | while horizon_light_min-horizon_light_max>light_gap: 78 | if horizon_angle-1<0: 79 | horizon_angle=0 80 | else: 81 | horizon_angle=horizon_angle-1 82 | servodriver(p_horizon,horizon_angle) 83 | time.sleep(0.5) 84 | horizon_light_min=ADC_Read(horizon_light_min_channel) 85 | horizon_light_max=ADC_Read(horizon_light_max_channel) 86 | while vertical_light_max-vertical_light_min>light_gap: 87 | if vertical_angle+1>180: 88 | vertical_angle=180 89 | else: 90 | vertical_angle=vertical_angle+1 91 | servodriver(p_vertical,vertical_angle) 92 | time.sleep(0.5) 93 | vertical_light_min=ADC_Read(vertical_light_min_channel) 94 | vertical_light_max=ADC_Read(vertical_light_max_channel) 95 | while vertical_light_min-vertical_light_max>light_gap: 96 | if vertical_angle-1<0: 97 | vertical_angle=0 98 | else: 99 | vertical_angle=vertical_angle-1 100 | servodriver(p_vertical,vertical_angle) 101 | time.sleep(0.5) 102 | vertical_light_min=ADC_Read(vertical_light_min_channel) 103 | vertical_light_max=ADC_Read(vertical_light_max_channel) 104 | 105 | ''' 106 | #for i in range(25,125,1): 107 | for i in range(0,181,2): 108 | servodriver(p_horizon,i) 109 | servodriver(p_vertical,i/2.0) 110 | print i 111 | time.sleep(0.5) 112 | ''' 113 | ''' 114 | while(True): 115 | for i in range(0,360,10): 116 | p.ChangeDutyCycle(12.5-5*i/360) 117 | time.sleep(1) 118 | for i in range(0,360,10): 119 | p.ChangeDutyCycle(7.5-5*i/360) 120 | time.sleep(1) 121 | ''' 122 | --------------------------------------------------------------------------------