common.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. # -*- coding: utf-8 -*-
  2. #!/usr/bin/env python
  3. import os
  4. from typing import List
  5. from functools import partial
  6. from dotenv import load_dotenv
  7. from passlib.context import CryptContext
  8. load_dotenv('.env.simulator')
  9. class CMD(object):
  10. HAND_SHAKE = 200
  11. GET_INFO = 201
  12. CONFIG_DEVICE = 202
  13. #: init mobile payment, publish by app
  14. MOBILE_PAY_INIT = 203
  15. #: finish mobile payment, publish by the device smartbox
  16. MOBILE_PAY_FIN = 204
  17. PUT_COIN = 205
  18. HEARTBEAT = 207
  19. OFFLINE = 208
  20. DEVICE_TOPIC_PREFIX = 'smart_box'
  21. SERVER_TOPIC_PREFIX = 'server'
  22. MQTT_QOS = 0
  23. MQTT_QOS1 = 1
  24. MQTT_HOSTNAME = os.environ.get('MQTT_HOSTNAME', '127.0.0.1')
  25. MQTT_PORT = int(os.environ.get('MQTT_PORT', 1999))
  26. MQTT_BROKER_URL = os.environ.get('MQTT_BROKER_URL', 'localhost')
  27. MQTT_BROKER_SCHEME = os.environ.get('MQTT_BROKER_SCHEME', 'tcp')
  28. DEFAULT_DEVICE_IMEI = os.environ.get('DEFAULT_DEVICE_IMEI')
  29. # constants
  30. SINGLE_LEVEL_ALL = '+'
  31. MULTI_LEVEL_ALL = '#'
  32. def get_topic(prefix, imei, cmd):
  33. # type: (str, str, int)->str
  34. return '{prefix}/{imei}/{cmd}'.format(prefix=prefix, imei=imei, cmd=cmd)
  35. def get_device_topic(imei, cmd):
  36. # type: (str, int)->str
  37. return get_topic(prefix=DEVICE_TOPIC_PREFIX, imei=imei, cmd=cmd)
  38. def get_server_topic(imei, cmd):
  39. # type: (str, int)->str
  40. return get_topic(prefix=SERVER_TOPIC_PREFIX, imei=imei, cmd=cmd)
  41. #: topics
  42. handshake_topic = partial(get_server_topic, cmd=CMD.HAND_SHAKE)
  43. get_info_topic = partial(get_server_topic, cmd=CMD.GET_INFO)
  44. config_device_topic = partial(get_server_topic, cmd=CMD.CONFIG_DEVICE)
  45. mobile_pay_init_topic = partial(get_server_topic, cmd=CMD.MOBILE_PAY_INIT)
  46. mobile_pay_finish_topic = partial(get_server_topic, cmd=CMD.MOBILE_PAY_FIN)
  47. put_coin_topic = partial(get_server_topic, cmd=CMD.PUT_COIN)
  48. heartbeat_topic = partial(get_server_topic, cmd=CMD.HEARTBEAT)
  49. offline_topic = partial(get_server_topic, cmd=CMD.OFFLINE)
  50. SERVER_TOPICS = [
  51. get_server_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.HAND_SHAKE),
  52. get_server_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.GET_INFO),
  53. get_server_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.CONFIG_DEVICE),
  54. get_server_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.MOBILE_PAY_INIT),
  55. get_server_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.MOBILE_PAY_FIN),
  56. get_server_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.PUT_COIN),
  57. get_server_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.HEARTBEAT),
  58. get_server_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.OFFLINE),
  59. ] # type: List[str]
  60. DEVICE_TOPICS = [
  61. get_device_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.HAND_SHAKE),
  62. get_device_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.GET_INFO),
  63. get_device_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.CONFIG_DEVICE),
  64. get_device_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.MOBILE_PAY_INIT),
  65. get_device_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.MOBILE_PAY_FIN),
  66. get_device_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.PUT_COIN),
  67. get_device_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.HEARTBEAT),
  68. get_device_topic(imei=SINGLE_LEVEL_ALL, cmd=CMD.OFFLINE),
  69. ]
  70. DEV_STATUS_IDLE = 0
  71. DEV_STATUS_BUSY = 1
  72. DEV_OFFLINE = 0
  73. DEV_ONLINE = 1
  74. class BaseProtocolHandler(object):
  75. def handle(self, payload):
  76. methname = 'handle_{cmd}'.format(cmd=payload['cmd'])
  77. method = getattr(self, methname)
  78. if not method:
  79. raise RuntimeError('no command {} handler found!')
  80. else:
  81. method(payload)
  82. #: encryption
  83. pwd_context = CryptContext(
  84. schemes=["pbkdf2_sha256"],
  85. default="pbkdf2_sha256",
  86. pbkdf2_sha256__default_rounds=30000
  87. )
  88. def encrypt_password(password):
  89. return pwd_context.hash(password)
  90. def check_encrypted_password(password, hashed):
  91. return pwd_context.verify(password, hashed)