Browse Source

Merge branch 'dev' of github.com:xoseperez/espurna into dev

sensors
Xose Pérez 5 years ago
parent
commit
3bfd258e4d
5 changed files with 106 additions and 78 deletions
  1. +5
    -0
      code/espurna/relay.ino
  2. +7
    -1
      code/espurna/sensors/PMSX003Sensor.h
  3. +27
    -25
      code/memanalyzer.py
  4. +56
    -45
      code/ota.py
  5. +11
    -7
      pre-commit

+ 5
- 0
code/espurna/relay.ino View File

@ -83,6 +83,11 @@ void _relayProviderStatus(unsigned char id, bool status) {
Serial.write(id + 1); Serial.write(id + 1);
Serial.write(status); Serial.write(status);
Serial.write(0xA1 + status + id); Serial.write(0xA1 + status + id);
// The serial init are not full recognized by relais board.
// References: https://github.com/xoseperez/espurna/issues/1519 , https://github.com/xoseperez/espurna/issues/1130
delay(100);
Serial.flush(); Serial.flush();
#endif #endif


+ 7
- 1
code/espurna/sensors/PMSX003Sensor.h View File

@ -22,6 +22,7 @@
#define PMS_TYPE_X003_9 1 #define PMS_TYPE_X003_9 1
#define PMS_TYPE_5003T 2 #define PMS_TYPE_5003T 2
#define PMS_TYPE_5003ST 3 #define PMS_TYPE_5003ST 3
#define PMS_TYPE_5003S 4
// Sensor type specified data // Sensor type specified data
#define PMS_SLOT_MAX 4 #define PMS_SLOT_MAX 4
@ -35,7 +36,8 @@ const static struct {
{"PMSX003", 13, 3, {MAGNITUDE_PM1dot0, MAGNITUDE_PM2dot5, MAGNITUDE_PM10}}, {"PMSX003", 13, 3, {MAGNITUDE_PM1dot0, MAGNITUDE_PM2dot5, MAGNITUDE_PM10}},
{"PMSX003_9", 9, 3, {MAGNITUDE_PM1dot0, MAGNITUDE_PM2dot5, MAGNITUDE_PM10}}, {"PMSX003_9", 9, 3, {MAGNITUDE_PM1dot0, MAGNITUDE_PM2dot5, MAGNITUDE_PM10}},
{"PMS5003T", 13, 3, {MAGNITUDE_PM2dot5, MAGNITUDE_TEMPERATURE, MAGNITUDE_HUMIDITY}}, {"PMS5003T", 13, 3, {MAGNITUDE_PM2dot5, MAGNITUDE_TEMPERATURE, MAGNITUDE_HUMIDITY}},
{"PMS5003ST", 17, 4, {MAGNITUDE_PM2dot5, MAGNITUDE_TEMPERATURE, MAGNITUDE_HUMIDITY, MAGNITUDE_HCHO}}
{"PMS5003ST", 17, 4, {MAGNITUDE_PM2dot5, MAGNITUDE_TEMPERATURE, MAGNITUDE_HUMIDITY, MAGNITUDE_HCHO}},
{"PMS5003S", 13, 3, {MAGNITUDE_PM2dot5, MAGNITUDE_PM10, MAGNITUDE_HCHO}},
}; };
// [MAGIC][LEN][DATA9|13|17][SUM] // [MAGIC][LEN][DATA9|13|17][SUM]
@ -306,6 +308,10 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
_slot_values[1] = (double)data[13] / 10; _slot_values[1] = (double)data[13] / 10;
_slot_values[2] = (double)data[14] / 10; _slot_values[2] = (double)data[14] / 10;
_slot_values[3] = (double)data[12] / 1000; _slot_values[3] = (double)data[12] / 1000;
} else if (_type == PMS_TYPE_5003S) {
_slot_values[0] = data[4];
_slot_values[1] = data[5];
_slot_values[2] = (double)data[12] / 1000;
} else if (_type == PMS_TYPE_5003T) { } else if (_type == PMS_TYPE_5003T) {
_slot_values[0] = data[4]; _slot_values[0] = data[4];
_slot_values[1] = (double)data[10] / 10; _slot_values[1] = (double)data[10] / 10;


+ 27
- 25
code/memanalyzer.py View File

@ -19,15 +19,16 @@ import argparse
import os import os
import re import re
import shlex import shlex
import subprocess
import sys import sys
from collections import OrderedDict from collections import OrderedDict
from sortedcontainers import SortedDict from sortedcontainers import SortedDict
import subprocess
if (sys.version_info > (3, 0)):
from subprocess import getstatusoutput as getstatusoutput
if sys.version_info > (3, 0):
from subprocess import getstatusoutput
else: else:
from commands import getstatusoutput as getstatusoutput
from commands import getstatusoutput
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
@ -55,7 +56,7 @@ def file_size(file):
def analyse_memory(elf_file): def analyse_memory(elf_file):
command = "%s -t '%s'" % (objdump_binary, elf_file)
command = "{} -t '{}'".format(objdump_binary, elf_file)
response = subprocess.check_output(shlex.split(command)) response = subprocess.check_output(shlex.split(command))
if isinstance(response, bytes): if isinstance(response, bytes):
response = response.decode('utf-8') response = response.decode('utf-8')
@ -66,8 +67,8 @@ def analyse_memory(elf_file):
ret = {} ret = {}
for (id_, _) in list(sections.items()): for (id_, _) in list(sections.items()):
section_start_token = " _%s_start" % id_
section_end_token = " _%s_end" % id_
section_start_token = " _{}_start".format(id_)
section_end_token = " _{}_end".format(id_)
section_start = -1 section_start = -1
section_end = -1 section_end = -1
for line in lines: for line in lines:
@ -92,24 +93,26 @@ def analyse_memory(elf_file):
# print("{0: >10}|{1: >30}|{2:12X}|{3:12X}|{4:8}".format(id_, descr, section_start, section_end, section_length)) # print("{0: >10}|{1: >30}|{2:12X}|{3:12X}|{4:8}".format(id_, descr, section_start, section_end, section_length))
# i += 1 # i += 1
# print("Total Used RAM : %d" % usedRAM)
# print("Free RAM : %d" % (TOTAL_DRAM - usedRAM))
# print("Free IRam : %d" % usedIRAM)
# print("Total Used RAM : {:d}".format(usedRAM))
# print("Free RAM : {:d}".format(TOTAL_DRAM - usedRAM))
# print("Free IRam : {:d}".format(usedIRAM))
return ret return ret
def run(env_, modules_): def run(env_, modules_):
flags = "" flags = ""
for item in modules_.items():
flags += "-D%s_SUPPORT=%d " % item
command = "ESPURNA_BOARD=\"WEMOS_D1_MINI_RELAYSHIELD\" ESPURNA_FLAGS=\"%s\" platformio run --silent --environment %s 2>/dev/null" % (flags, env_)
for k, v in modules_.items():
flags += "-D{}_SUPPORT={:d} ".format(k, v)
command = "ESPURNA_BOARD=\"WEMOS_D1_MINI_RELAYSHIELD\" ESPURNA_FLAGS=\"{}\" platformio run --silent --environment {} 2>/dev/null".format(flags, env_)
subprocess.check_call(command, shell=True) subprocess.check_call(command, shell=True)
def calc_free(module): def calc_free(module):
free = 80 * 1024 - module['data'] - module['rodata'] - module['bss'] free = 80 * 1024 - module['data'] - module['rodata'] - module['bss']
free = free + (16 - free % 16) free = free + (16 - free % 16)
module['free'] = free module['free'] = free
def modules_get(): def modules_get():
modules_ = SortedDict() modules_ = SortedDict()
for line in open("espurna/config/arduino.h"): for line in open("espurna/config/arduino.h"):
@ -120,7 +123,8 @@ def modules_get():
del modules_['NETBIOS'] del modules_['NETBIOS']
return modules_ return modules_
try:
if __name__ == '__main__':
# Parse command line options # Parse command line options
parser = argparse.ArgumentParser(description=description) parser = argparse.ArgumentParser(description=description)
@ -160,7 +164,7 @@ try:
# Check test modules exist # Check test modules exist
for module in test_modules: for module in test_modules:
if module not in available_modules: if module not in available_modules:
print("Module %s not found" % module)
print("Module {} not found".format(module))
sys.exit(2) sys.exit(2)
# Define base configuration # Define base configuration
@ -173,9 +177,9 @@ try:
# Show init message # Show init message
if len(test_modules) > 0: if len(test_modules) > 0:
print("Analyzing module(s) %s on top of %s configuration\n" % (", ".join(test_modules), "CORE" if args.core > 0 else "DEFAULT"))
print("Analyzing module(s) {} on top of {} configuration\n".format(", ".join(test_modules), "CORE" if args.core > 0 else "DEFAULT"))
else: else:
print("Analyzing %s configuration\n" % ("CORE" if args.core > 0 else "DEFAULT"))
print("Analyzing {} configuration\n".format("CORE" if args.core > 0 else "DEFAULT"))
output_format = "{:<20}|{:<15}|{:<15}|{:<15}|{:<15}|{:<15}|{:<15}|{:<15}" output_format = "{:<20}|{:<15}|{:<15}|{:<15}|{:<15}|{:<15}|{:<15}|{:<15}"
print(output_format.format( print(output_format.format(
@ -211,8 +215,8 @@ try:
# Build the core without modules to get base memory usage # Build the core without modules to get base memory usage
run(env, modules) run(env, modules)
base = analyse_memory(".pioenvs/%s/firmware.elf" % env)
base['size'] = file_size(".pioenvs/%s/firmware.bin" % env)
base = analyse_memory(".pioenvs/{}/firmware.elf".format(env))
base['size'] = file_size(".pioenvs/{}/firmware.bin".format(env))
calc_free(base) calc_free(base)
print(output_format.format( print(output_format.format(
"CORE" if args.core == 1 else "DEFAULT", "CORE" if args.core == 1 else "DEFAULT",
@ -231,8 +235,8 @@ try:
modules[module] = 1 modules[module] = 1
run(env, modules) run(env, modules)
results[module] = analyse_memory(".pioenvs/%s/firmware.elf" % env)
results[module]['size'] = file_size(".pioenvs/%s/firmware.bin" % env)
results[module] = analyse_memory(".pioenvs/{}/firmware.elf".format(env))
results[module]['size'] = file_size(".pioenvs/{}/firmware.bin".format(env))
calc_free(results[module]) calc_free(results[module])
modules[module] = 0 modules[module] = 0
@ -253,8 +257,8 @@ try:
for module in test_modules: for module in test_modules:
modules[module] = 1 modules[module] = 1
run(env, modules) run(env, modules)
total = analyse_memory(".pioenvs/%s/firmware.elf" % env)
total['size'] = file_size(".pioenvs/%s/firmware.bin" % env)
total = analyse_memory(".pioenvs/{}/firmware.elf".format(env))
total['size'] = file_size(".pioenvs/{}/firmware.bin".format(env))
calc_free(total) calc_free(total)
if len(test_modules) > 1: if len(test_modules) > 1:
@ -279,7 +283,5 @@ try:
total['size'], total['size'],
)) ))
except:
raise
print("\n") print("\n")

+ 56
- 45
code/ota.py View File

@ -8,14 +8,14 @@
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
from __future__ import print_function from __future__ import print_function
import shutil
import argparse import argparse
import os
import re import re
import shutil
import socket import socket
import subprocess import subprocess
import sys import sys
import time import time
import os
from zeroconf import ServiceBrowser, ServiceStateChange, Zeroconf from zeroconf import ServiceBrowser, ServiceStateChange, Zeroconf
@ -33,6 +33,7 @@ description = "ESPurna OTA Manager v0.3"
devices = [] devices = []
discover_last = 0 discover_last = 0
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
def on_service_state_change(zeroconf, service_type, name, state_change): def on_service_state_change(zeroconf, service_type, name, state_change):
@ -61,7 +62,7 @@ def on_service_state_change(zeroconf, service_type, name, state_change):
} }
for key, item in info.properties.items(): for key, item in info.properties.items():
device[key.decode('UTF-8')] = item.decode('UTF-8');
device[key.decode('UTF-8')] = item.decode('UTF-8')
# rename fields (needed for sorting by name) # rename fields (needed for sorting by name)
device['app'] = device['app_name'] device['app'] = device['app_name']
@ -75,35 +76,35 @@ def list_devices():
""" """
Shows the list of discovered devices Shows the list of discovered devices
""" """
output_format="{:>3} {:<14} {:<15} {:<17} {:<12} {:<12} {:<25} {:<8} {:<8} {:<10}"
output_format = "{:>3} {:<14} {:<15} {:<17} {:<12} {:<12} {:<25} {:<8} {:<8} {:<10}"
print(output_format.format( print(output_format.format(
"#",
"HOSTNAME",
"IP",
"MAC",
"APP",
"VERSION",
"DEVICE",
"MEM_SIZE",
"SDK_SIZE",
"FREE_SPACE"
"#",
"HOSTNAME",
"IP",
"MAC",
"APP",
"VERSION",
"DEVICE",
"MEM_SIZE",
"SDK_SIZE",
"FREE_SPACE"
)) ))
print("-" * 139) print("-" * 139)
index = 0 index = 0
for device in devices: for device in devices:
index = index + 1
index += 1
print(output_format.format( print(output_format.format(
index,
device.get('hostname', ''),
device.get('ip', ''),
device.get('mac', ''),
device.get('app_name', ''),
device.get('app_version', ''),
device.get('target_board', ''),
device.get('mem_size', 0),
device.get('sdk_size', 0),
device.get('free_space', 0),
index,
device.get('hostname', ''),
device.get('ip', ''),
device.get('mac', ''),
device.get('app_name', ''),
device.get('app_version', ''),
device.get('target_board', ''),
device.get('mem_size', 0),
device.get('sdk_size', 0),
device.get('free_space', 0),
)) ))
print() print()
@ -120,11 +121,13 @@ def get_boards():
boards.append(m.group(1)) boards.append(m.group(1))
return sorted(boards) return sorted(boards)
def get_device_size(device): def get_device_size(device):
if device.get('mem_size', 0) == device.get('sdk_size', 0): if device.get('mem_size', 0) == device.get('sdk_size', 0):
return int(device.get('mem_size', 0)) / 1024 return int(device.get('mem_size', 0)) / 1024
return 0 return 0
def get_empty_board(): def get_empty_board():
""" """
Returns the empty structure of a board to flash Returns the empty structure of a board to flash
@ -132,12 +135,13 @@ def get_empty_board():
board = {'board': '', 'ip': '', 'size': 0, 'auth': '', 'flags': ''} board = {'board': '', 'ip': '', 'size': 0, 'auth': '', 'flags': ''}
return board return board
def get_board_by_index(index): def get_board_by_index(index):
""" """
Returns the required data to flash a given board Returns the required data to flash a given board
""" """
board = {} board = {}
if 1 <= index and index <= len(devices):
if 1 <= index <= len(devices):
device = devices[index - 1] device = devices[index - 1]
board['hostname'] = device.get('hostname') board['hostname'] = device.get('hostname')
board['board'] = device.get('target_board', '') board['board'] = device.get('target_board', '')
@ -145,6 +149,7 @@ def get_board_by_index(index):
board['size'] = get_device_size(device) board['size'] = get_device_size(device)
return board return board
def get_board_by_mac(mac): def get_board_by_mac(mac):
""" """
Returns the required data to flash a given board Returns the required data to flash a given board
@ -161,6 +166,7 @@ def get_board_by_mac(mac):
return board return board
return None return None
def get_board_by_hostname(hostname): def get_board_by_hostname(hostname):
""" """
Returns the required data to flash a given board Returns the required data to flash a given board
@ -178,6 +184,7 @@ def get_board_by_hostname(hostname):
return board return board
return None return None
def input_board(): def input_board():
""" """
Grabs info from the user about what device to flash Grabs info from the user about what device to flash
@ -189,10 +196,10 @@ def input_board():
except ValueError: except ValueError:
index = 0 index = 0
if index < 0 or len(devices) < index: if index < 0 or len(devices) < index:
print("Board number must be between 1 and %s\n" % str(len(devices)))
print("Board number must be between 1 and {}\n".format(str(len(devices))))
return None return None
board = get_board_by_index(index);
board = get_board_by_index(index)
# Choose board type if none before # Choose board type if none before
if len(board.get('board', '')) == 0: if len(board.get('board', '')) == 0:
@ -201,15 +208,15 @@ def input_board():
count = 1 count = 1
boards = get_boards() boards = get_boards()
for name in boards: for name in boards:
print("%3d\t%s" % (count, name))
count = count + 1
print("{:3d}\t{}".format(count, name))
count += 1
print() print()
try: try:
index = int(input("Choose the board type you want to flash: ")) index = int(input("Choose the board type you want to flash: "))
except ValueError: except ValueError:
index = 0 index = 0
if index < 1 or len(boards) < index: if index < 1 or len(boards) < index:
print("Board number must be between 1 and %s\n" % str(len(boards)))
print("Board number must be between 1 and {}\n".format(str(len(boards))))
return None return None
board['board'] = boards[index - 1] board['board'] = boards[index - 1]
@ -227,12 +234,14 @@ def input_board():
return board return board
def boardname(board): def boardname(board):
return board.get('hostname', board['ip']) return board.get('hostname', board['ip'])
def store(device, env): def store(device, env):
source = ".pioenvs/%s/firmware.elf" % env
destination = ".pioenvs/elfs/%s.elf" % boardname(device).lower()
source = ".pioenvs/{}/firmware.elf".format(env)
destination = ".pioenvs/elfs/{}.elf".format(boardname(device).lower())
dst_dir = os.path.dirname(destination) dst_dir = os.path.dirname(destination)
if not os.path.exists(dst_dir): if not os.path.exists(dst_dir):
@ -240,6 +249,7 @@ def store(device, env):
shutil.move(source, destination) shutil.move(source, destination)
def run(device, env): def run(device, env):
print("Building and flashing image over-the-air...") print("Building and flashing image over-the-air...")
environ = os.environ.copy() environ = os.environ.copy()
@ -253,6 +263,7 @@ def run(device, env):
store(device, env) store(device, env)
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
if __name__ == '__main__': if __name__ == '__main__':
@ -272,13 +283,13 @@ if __name__ == '__main__':
print(description) print(description)
print() print()
# Look for sevices
# Look for services
zeroconf = Zeroconf() zeroconf = Zeroconf()
browser = ServiceBrowser(zeroconf, "_arduino._tcp.local.", handlers=[on_service_state_change]) browser = ServiceBrowser(zeroconf, "_arduino._tcp.local.", handlers=[on_service_state_change])
discover_last = time.time() discover_last = time.time()
while time.time() < discover_last + DISCOVER_TIMEOUT: while time.time() < discover_last + DISCOVER_TIMEOUT:
None
#zeroconf.close()
pass
# zeroconf.close()
if len(devices) == 0: if len(devices) == 0:
print("Nothing found!\n") print("Nothing found!\n")
@ -287,7 +298,7 @@ if __name__ == '__main__':
# Sort list # Sort list
field = args.sort.lower() field = args.sort.lower()
if field not in devices[0]: if field not in devices[0]:
print("Unknown field '%s'\n" % field)
print("Unknown field '{}'\n".format(field))
sys.exit(1) sys.exit(1)
devices = sorted(devices, key=lambda device: device.get(field, '')) devices = sorted(devices, key=lambda device: device.get(field, ''))
@ -322,23 +333,23 @@ if __name__ == '__main__':
queue = sorted(queue, key=lambda device: device.get('board', '')) queue = sorted(queue, key=lambda device: device.get('board', ''))
# Flash eash board
# Flash each board
for board in queue: for board in queue:
# Flash core version? # Flash core version?
if args.core > 0: if args.core > 0:
board['flags'] = "-DESPURNA_CORE " + board['flags'] board['flags'] = "-DESPURNA_CORE " + board['flags']
env = "esp8266-%dm-ota" % board['size']
env = "esp8266-{:d}m-ota".format(board['size'])
# Summary # Summary
print() print()
print("HOST = %s" % boardname(board))
print("IP = %s" % board['ip'])
print("BOARD = %s" % board['board'])
print("AUTH = %s" % board['auth'])
print("FLAGS = %s" % board['flags'])
print("ENV = %s" % env)
print("HOST = {}".format(boardname(board)))
print("IP = {}".format(board['ip']))
print("BOARD = {}".format(board['board']))
print("AUTH = {}".format(board['auth']))
print("FLAGS = {}".format(board['flags']))
print("ENV = {}".format(env))
response = True response = True
if args.yes == 0: if args.yes == 0:


+ 11
- 7
pre-commit View File

@ -15,17 +15,18 @@ Copy this file to .git/hooks/
""" """
import os import os
import sys
import string
import re import re
import string
import sys
from subprocess import call, check_output from subprocess import call, check_output
try: try:
from urllib.parse import urlparse from urllib.parse import urlparse
except ImportError: except ImportError:
from urlparse import urlparse from urlparse import urlparse
from fileinput import FileInput from fileinput import FileInput
# https://github.com/python/cpython/commit/6cb7b659#diff-78790b53ff259619377058acd4f74672 # https://github.com/python/cpython/commit/6cb7b659#diff-78790b53ff259619377058acd4f74672
if sys.version_info[0] < 3: if sys.version_info[0] < 3:
class FileInputCtx(FileInput): class FileInputCtx(FileInput):
@ -35,6 +36,7 @@ if sys.version_info[0] < 3:
def __exit__(self, type, value, traceback): def __exit__(self, type, value, traceback):
self.close() self.close()
FileInput = FileInputCtx FileInput = FileInputCtx
@ -91,15 +93,15 @@ def espurna_get_version(base, version_h="code/espurna/config/version.h"):
TEMPLATES = { TEMPLATES = {
"![travis]": "[![travis](https://travis-ci.org/{USER}/{REPO}.svg?branch={BRANCH})]" "![travis]": "[![travis](https://travis-ci.org/{USER}/{REPO}.svg?branch={BRANCH})]"
"(https://travis-ci.org/{USER}/{REPO})\n",
"![version]": "[![version](https://img.shields.io/badge/version-{VERSION:escape_hyphen}-brightgreen.svg)](CHANGELOG.md)\n",
"(https://travis-ci.org/{USER}/{REPO})\n",
"![version]": "[![version](https://img.shields.io/badge/version-{VERSION:escape_hyphen}-brightgreen.svg)]"
"(CHANGELOG.md)\n",
"![branch]": "[![branch](https://img.shields.io/badge/branch-{BRANCH:escape_hyphen}-orange.svg)]" "![branch]": "[![branch](https://img.shields.io/badge/branch-{BRANCH:escape_hyphen}-orange.svg)]"
"(https://github.com/{USER}/{REPO}/tree/{BRANCH}/)\n",
"(https://github.com/{USER}/{REPO}/tree/{BRANCH}/)\n",
} }
README = "README.md" README = "README.md"
if __name__ == "__main__": if __name__ == "__main__":
base = os.getcwd() base = os.getcwd()
@ -117,6 +119,7 @@ if __name__ == "__main__":
for k, tmpl in TEMPLATES.items() for k, tmpl in TEMPLATES.items()
] ]
def fmt_line(line): def fmt_line(line):
for match, tmpl in templates: for match, tmpl in templates:
if match in line: if match in line:
@ -124,6 +127,7 @@ if __name__ == "__main__":
return line return line
path = os.path.join(base, README) path = os.path.join(base, README)
with FileInput(path, inplace=True) as readme: with FileInput(path, inplace=True) as readme:


Loading…
Cancel
Save