Files
ESPEasy/test/node.py
T
2018-01-11 01:35:32 +01:00

173 lines
4.9 KiB
Python

### Generic lowlevel ESP and espeasy per-node stuff.
### Used for things like flashing, serial communication, resetting, wificonfig, http communication
import serial
import sys
import time
import subprocess
import wificonfig
import requests
import serial.tools.miniterm
import re
from espcore import *
class Node():
def __init__(self, config, id):
self.log=logging.getLogger(id)
self.log.debug("{type} has ip {ip}".format(id=id, **config))
self._config=config
self._id=id
self._url="http://{ip}/".format(**self._config)
self._serial_initialized=False
def serial_needed(self):
"""call this at least once if you need serial stuff"""
if not hasattr(self,"_serial"):
self._serial=serial.Serial(port=self._config['port'], baudrate=115200, timeout=1, write_timeout=1)
def pingserial(self, timeout=60):
"""waits until espeasy reponds via serial"""
self.serial_needed()
self._serial.reset_input_buffer();
self.log.debug("Waiting for serial response")
start_time=time.time()
while (time.time()-start_time)< int(timeout):
self._serial.write(bytes('.\n', 'ascii'));
a=True
while a!=b'':
a=self._serial.readline()
if a==b"Unknown command!\r\n":
self.log.debug("Got serial response")
self._serial.reset_input_buffer();
return
raise(Exception("Timeout!"))
def reboot(self):
'''reboot the esp via the serial DTR line'''
self.serial_needed()
self._serial.setDTR(0)
time.sleep(0.1)
self._serial.setDTR(1)
def pingwifi(self, timeout=60):
"""waits until espeasy reponds via wifi"""
self.log.debug("Waiting for ping reply")
start_time=time.time()
while (time.time()-start_time)< int(timeout):
# log(".")
if not subprocess.call(["ping", "-w", "1", "-c", "1", self._config['ip']], stdout=subprocess.DEVNULL):
self.log.debug("Got ping reply")
return
raise(Exception("Timeout!"))
def wificonfig(self, timeout=60):
"""configure wifi via serial and make sure esp is online and pingable."""
self.serial_needed()
self.reboot()
self.pingserial(timeout=timeout)
self.log.info("Configuring wifi")
serial_str="wifissid {ssid}\nwifikey {password}\nip {ip}\nsave\nreboot\n".format(ssid=wificonfig.ssid, password=wificonfig.password, ip=self._config['ip'])
self._serial.write(bytes(serial_str, 'ascii'));
self.pingwifi(timeout=timeout)
def build(self):
"""compile binary"""
subprocess.check_call(self._config['build_cmd'].format(**self._config), shell=True, cwd='..')
def flashserial(self):
"""flash binary to esp via serial"""
self.serial_needed()
subprocess.check_call(self._config['flash_cmd'].format(**self._config), shell=True, cwd='..')
time.sleep(1)
#to prevent hangs when ESPEasy tries to reboot via ESP.reboot (due to an ESP/lib bug)
self.reboot()
def serial(self):
"""open serial terminal to esp"""
self.serial_needed()
subprocess.check_call("platformio serialports monitor --baud 115200 --port {port} --echo".format(**self._config), shell=True, cwd='..')
# print("JA")
# term=serial.tools.miniterm.Miniterm(self._serial)
# term.start()
# term.join()
# print("kk")
def erase(self):
"""erase flash via serial"""
self.serial_needed()
subprocess.check_call("esptool.py --port {port} -b 1500000 erase_flash".format(**self._config), shell=True, cwd='..')
def bfs(self):
"""build + flashserial + serial, all in one"""
self.build()
self.flashserial()
self.serial()
def http_post(self, page, params, data=None, twice=False):
"""http post to espeasy webinterface. (GET if data is None)"""
# transform easy copy/pastable chromium data into a dict
params_dict={}
for line in params.split("\n"):
m=re.match(" *(.*?):(.*)",line)
if (m):
params_dict[m.group(1)]=m.group(2)
if data:
data_dict={}
for line in data.split("\n"):
m=re.match(" *(.*?):(.*)",line)
if (m):
data_dict[m.group(1)]=m.group(2)
else:
data_dict=None
r=requests.post(
self._url+page,
params=params_dict,
data=data_dict
)
r.raise_for_status()
if twice:
r=requests.post(
self._url+page,
params=params_dict,
data=data_dict
)
r.raise_for_status()