123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- import struct
- from typing import TYPE_CHECKING
- from apps.web.core.accounting import Accounting
- from apps.web.device.models import Device
- from apps.web.device.timescale import FluentedEngine, OfflineManager
- from script.eventer.handlers import Handler
- logger = logging.getLogger(__name__)
- if TYPE_CHECKING:
- pass
- class ShakeHandHandler(Handler):
- def parse(self):
- logger.debug('orginal payload len: {}'.format(len(self.payload)))
- payload = struct.pack('<{}s4s'.format(len(self.payload)), self.payload, '0000')
- logger.debug('now payload len: {}'.format(len(payload)))
- offset = 0
- ts = struct.unpack_from('<I', payload, offset = offset)[0]
- offset = offset + 4
- signal = struct.unpack_from('<B', payload, offset = offset)[0]
- offset = offset + 1
- logger.debug('ts = {}; signal = {}'.format(ts, signal))
- rv = {
- 'ts': ts,
- 'signal': signal
- }
- while offset < (len(payload) - 4):
- _type = struct.unpack_from('<B', payload, offset = offset)[0]
- offset = offset + 1
- if _type == 0x01:
- # coins: 2
- coins = struct.unpack_from('<H', payload, offset = offset)[0]
- offset = offset + 2
- logger.debug('coins = {}'.format(coins))
- rv.update({'today_coins': coins})
- elif _type == 0x02:
- # start_no:1, end_no:1, used_ports: 1, [port:1, power:2]*
- rv.update({'powers': {}})
- start_no = struct.unpack_from('<B', payload, offset = offset)[0]
- offset = offset + 1
- end_no = struct.unpack_from('<B', payload, offset = offset)[0]
- offset = offset + 1
- used = struct.unpack_from('<B', payload, offset = offset)[0]
- offset = offset + 1
- logger.debug('start_no = {}; end_no = {}; used ports = {}'.format(start_no, end_no, used))
- for i in range(0, used):
- port, power = struct.unpack_from('<BH', payload, offset = offset)
- offset = offset + 3
- logger.debug('port = {}, power = {}'.format(port, power))
- rv['powers'][str(port)] = {
- 'power': power
- # 'voltage': '-',
- # 'current': '-'
- }
- for i in range(start_no, end_no + 1):
- if str(i) not in rv['powers']:
- rv['powers'][str(i)] = {
- 'power': 0
- # 'voltage': '-',
- # 'current': '-'
- }
- elif _type == 0x03:
- # voltage: 2, start_no:1, end_no:1, used_ports: 1, [port:1, power:2, current:2]*
- rv.update({'powers': {}})
- voltage = struct.unpack_from('<H', payload, offset = offset)[0]
- voltage = str(round(float(voltage) / 10, 2))
- offset = offset + 2
- logger.debug('voltage = {}'.format(voltage))
- start_no = struct.unpack_from('<B', payload, offset = offset)[0]
- offset = offset + 1
- end_no = struct.unpack_from('<B', payload, offset = offset)[0]
- offset = offset + 1
- used = struct.unpack_from('<B', payload, offset = offset)[0]
- offset = offset + 1
- logger.debug('start_no = {}; end_no = {}; used ports = {}'.format(start_no, end_no, used))
- for i in range(0, used):
- port, power, current = struct.unpack_from('<BHH', payload, offset = offset)
- offset = offset + 5
- logger.debug('port = {}, power = {}, current = {}'.format(port, power, current))
- rv['powers'][str(port)] = {
- 'power': power,
- 'voltage': voltage,
- 'current': current
- }
- for i in range(start_no, end_no + 1):
- if str(i) not in rv['powers']:
- rv['powers'][str(i)] = {
- 'power': 0,
- 'voltage': voltage,
- 'current': 0
- }
- elif _type == 0x05:
- # start_no:1, end_no:1, used_ports: 1, [port:1, power:2]*
- rv.update({'powers': {}})
- start_no = struct.unpack_from('<B', payload, offset = offset)[0]
- offset = offset + 1
- end_no = struct.unpack_from('<B', payload, offset = offset)[0]
- offset = offset + 1
- used = struct.unpack_from('<B', payload, offset = offset)[0]
- offset = offset + 1
- logger.debug('start_no = {}; end_no = {}; used ports = {}'.format(start_no, end_no, used))
- for i in range(0, used):
- port, power = struct.unpack_from('<BH', payload, offset = offset)
- offset = offset + 3
- logger.debug('port = {}, power = {}'.format(port, power))
- rv['powers'][str(port)] = {
- 'power': self.dev.deviceAdapter.format_upload_power(power)
- # 'voltage': '-',
- # 'current': '-'
- }
- for i in range(start_no, end_no + 1):
- if str(i) not in rv['powers']:
- rv['powers'][str(i)] = {
- 'power': 0
- # 'voltage': '-',
- # 'current': '-'
- }
- # weifule 的设备
- elif _type == 0x06: # 订单号 + 已用金额
- length = struct.unpack_from('b', payload, offset=offset)[0]
- offset += 1
- order_id = struct.unpack_from('{}s'.format(length), payload, offset=offset)[0]
- offset += length
- money = struct.unpack_from('<H', payload, offset=offset)[0]
- offset += 2
- logger.info('upload heartbeat order=<{}>, money=<{}>'.format(order_id, money))
- from apps.web.user.models import ConsumeRecord
- from mongoengine import Q
- order = ConsumeRecord.objects.filter(Q(orderNo=order_id) | Q(startKey=order_id)).first()
- if not order:
- continue
- lts = order.servicedInfo.get('lts')
- if lts and lts['ts'] >= ts:
- continue
- else:
- order.servicedInfo['lts'] = {
- 'ts': ts,
- 'money': money
- }
- order.save()
- continue
- elif _type == 0x00:
- # 定制设备类型同步.由各设备类型自己解析和处理数据
- length = struct.unpack_from('<H', payload, offset = offset)[0]
- offset = offset + 2
- value = struct.unpack_from('{}s'.format(length), payload, offset = offset)[0]
- offset = offset + length
- self.dev.deviceAdapter.do_heartbeat(value, ts)
- if 'powers' in rv and not self.dev.support_power_graph:
- Device.get_collection().update_one({'devNo': self.dev.devNo}, {'$set': {'otherConf.supportPG': True}})
- Device.invalid_device_cache(self.dev.devNo)
- return rv
- def do(self):
- rv = self.parse()
- OfflineManager.discard_device_offline_notify(devNo = self.dev.devNo)
- ts = rv['ts']
- signal = rv['signal']
- FluentedEngine().in_signal_udp(devNo = self.dev.devNo, ts = ts, signal = signal, cmd = self.cmd)
- if 'today_coins' in rv:
- Accounting.syncOfflineCoin(self.dev,
- datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d'),
- int(rv['today_coins']))
- for port, item in rv.get('powers', {}).iteritems():
- FluentedEngine().in_power_udp(devNo = self.dev.devNo,
- port = str(port),
- ts = ts,
- power = item['power'],
- voltage = item.get('voltage', None),
- current = item.get('current', None))
|