Projet de remplacement du "RPiPasserelle" d'Otec.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cli.py 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #!/usr/bin/env python3
  2. # builtins
  3. import click
  4. from datetime import datetime
  5. import importlib
  6. import time
  7. import json
  8. import os
  9. import re
  10. import sys
  11. import time
  12. import urllib
  13. import uvicorn
  14. import requests
  15. from pyheatpump.logger import logger_init
  16. from pyheatpump.models import *
  17. CONTEXT_SETTINGS={
  18. 'default_map':{'run': {}}
  19. }
  20. @click.group(invoke_without_command=True, context_settings=CONTEXT_SETTINGS)
  21. @click.option('--version', is_flag=True)
  22. @click.pass_context
  23. def cli(ctx, version):
  24. """
  25. if version:
  26. from pyheatpump import version
  27. return click.echo(pyheatpump.version())
  28. """
  29. pass
  30. @click.option('--host', default=None)
  31. @click.option('--port', default=None)
  32. @cli.command()
  33. def run(host, port):
  34. logger = logger_init()
  35. from .config import (API_HOST, API_PORT)
  36. if not host:
  37. host = API_HOST
  38. if not port:
  39. port = API_PORT
  40. log_level = 'info'
  41. click.echo('Launching PyHeatpump application')
  42. uvicorn.run('pyheatpump.app:application',
  43. host=host,
  44. port=int(port),
  45. log_level=log_level,
  46. workers=1)
  47. @click.option('--type', '-t', default=None, multiple=True)
  48. @cli.command()
  49. def fetch(type):
  50. logger = logger_init()
  51. from pyheatpump import modbus
  52. try:
  53. if type is None:
  54. var_types = VariableType.getall()
  55. else:
  56. var_types = {}
  57. for label, var_type in VariableType.getall().items():
  58. if label in type or var_type.slabel in type:
  59. var_types[label] = var_type
  60. # Analog - float
  61. if 'Analog' in var_types.keys():
  62. analog = var_types['Analog']
  63. logger.info('Read analog variables in registers [{}, {}]'.format(
  64. analog.start_address, analog.end_address
  65. ))
  66. res = modbus.read_holding_registers(analog.start_address, analog.end_address)
  67. logger.debug(f'analog length : {len(res)}')
  68. for r in range(len(res)):
  69. var = Variable(**{
  70. 'type': analog,
  71. 'address': r + analog.start_address})
  72. if not var.exists():
  73. logger.info('Insert variable {}:{}'.format(
  74. var.type, var.address))
  75. var.insert()
  76. val = VariableValue(**{
  77. 'type': var.type,
  78. 'address': var.address,
  79. 'value': res[r]})
  80. val.insert()
  81. # Integer - int
  82. if 'Integer' in var_types.keys():
  83. integer = var_types['Integer']
  84. logger.info('Read integer variables in registers [{}, {}]'.format(
  85. integer.start_address, integer.end_address
  86. ))
  87. res = modbus.read_holding_registers(integer.start_address, integer.end_address)
  88. logger.debug(f'integer length : {len(res)}')
  89. for r in range(len(res)):
  90. var = Variable(**{
  91. 'type': integer,
  92. 'address': r + integer.start_address})
  93. if not var.exists():
  94. logger.info('Insert variable {}:{}'.format(
  95. var.type, var.address))
  96. var.insert()
  97. val = VariableValue(**{
  98. 'type': var.type,
  99. 'address': var.address,
  100. 'value': res[r]})
  101. val.insert()
  102. # Digital - bool
  103. if 'Digital' in var_types.keys():
  104. digital = var_types['Digital']
  105. logger.info('Read digital variables in coils [{}, {}]'.format(
  106. digital.start_address, digital.end_address
  107. ))
  108. res = modbus.read_coils(digital.start_address, digital.end_address)
  109. logger.debug(f'digital length : {len(res)}')
  110. for r in range(len(res)):
  111. var = Variable(**{
  112. 'type': digital,
  113. 'address': r + digital.start_address})
  114. if not var.exists():
  115. logger.info('Insert variable {}:{}'.format(
  116. var.type, var.address))
  117. var.insert()
  118. val = VariableValue(**{
  119. 'type': var.type,
  120. 'address': var.address,
  121. 'value': res[r]})
  122. val.insert()
  123. logger.info('Successfully read all variables')
  124. except Exception as exc:
  125. logger.error(exc)
  126. if modbus.serial_conn:
  127. modbus.serial_conn.close()
  128. @click.option('--since', is_flag=True)
  129. @cli.command()
  130. def supervise(since):
  131. logger = logger_init()
  132. build_url = lambda d: '{scheme}://{hostname}:{port}{path}'.format(**d)
  133. from .config import config, mac_address_init, get_last_update, set_last_update
  134. mac_address = config.get('heatpump','mac_address')
  135. if not re.match('^(([0-9a-f]{2}):?){6}$', mac_address, re.I):
  136. mac_address = mac_address_init()
  137. from .models.heatpump import Heatpump
  138. if not since:
  139. last_update = 0
  140. else:
  141. last_update = get_last_update()
  142. base_url = {
  143. 'scheme':config.get('supervisor', 'scheme'),
  144. 'hostname':config.get('supervisor', 'host'),
  145. 'port':config.getint('supervisor', 'port')
  146. }
  147. get_path = '/'.join((
  148. config.get('supervisor', 'get_path'),
  149. Heatpump(mac_address).macformat
  150. ))
  151. get_url = {
  152. **base_url,
  153. **{'path': get_path}
  154. }
  155. get_resp = requests.get(
  156. url=build_url(get_url),
  157. verify=False
  158. )
  159. control_data = get_resp.json()
  160. if Heatpump(mac_address).control(control_data):
  161. logger.info('GET to supervisor succeded : updated values')
  162. set_last_update(int(datetime.now().strftime('%s')))
  163. else:
  164. logger.warn('Unable to set data from supervisor\n{}'.format(control_data))
  165. time.sleep(3)
  166. post_packets = [
  167. Heatpump(mac_address, last_update, ['Analog']).packet,
  168. Heatpump(mac_address, last_update, ['Digital']).packet,
  169. Heatpump(mac_address, last_update, ['Integer']).packet
  170. ]
  171. post_url = {
  172. **base_url,
  173. **{'path': config.get('supervisor', 'post_path')}
  174. }
  175. logger.info(build_url(post_url))
  176. for packet in post_packets:
  177. logger.debug('Will send %s', packet)
  178. post_resp = requests.post(
  179. url=build_url(post_url),
  180. json=packet,
  181. verify=False,
  182. timeout=200
  183. )
  184. time.sleep(5)
  185. if post_resp.status_code == 200:
  186. logger.info('POST to supervisor succeeded')
  187. continue
  188. logger.info('POST to supervisor failed')
  189. set_last_update(int(datetime.now().strftime('%s')))