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

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