Refactorisé encore une fois la branche IDE_remote afin de pouvoir ajouter luatool que j'ai remis au goût du jour ;-)

This commit is contained in:
Christian Zufferey
2019-10-20 18:21:13 +02:00
parent 2bde7567fe
commit 37babf725b
38 changed files with 705 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
# Remise au goût du jour le petit script luatool.py
## Sources
https://github.com/4refr0nt/luatool
## Description
Le petit script python *luatool.py* permet d'automatiser le téléchargement de
scripts *.lua* sur un NodeMCU branché sur le port USB.
## Problématiques
La version actuelle datant de 2017 ne fonctionne plus avec les nouveaux firmwares de NodeMCU, il a y un problème de délai au moment de l'initialisation
## Corrections
* J'ai donc repris le code python et mis un petit délai de 0.5 secondes juste après l'initialisation du port série.
* J'ai aussi diminué le délai d'attente entre chaque ligne, passé de 0.3 sec à 0.03. Les téléchargement sont donc 10x plus rapides
* J'ai aussi mis un nouveau telnet serveur qui tient compte des tailles maximales des paquets TCP
zf191020.1819

View File

@@ -0,0 +1,15 @@
-- Scripts à charger après le boot pour démarrer le core system
print("\n boot.lua zf190916.2359 \n")
-- charge ses propres secrets
f= "secrets_energy.lua" if file.exists(f) then dofile(f) end
--f= "led_rgb.lua" if file.exists(f) then dofile(f) end
--f= "wifi_ap_start.lua" if file.exists(f) then dofile(f) end
f= "wifi_ap_stop.lua" if file.exists(f) then dofile(f) end
f= "wifi_cli_conf.lua" if file.exists(f) then dofile(f) end
f= "wifi_cli_start.lua" if file.exists(f) then dofile(f) end
f= "telnet_srv2.lua" if file.exists(f) then dofile(f) end
f= "web_ide2.lua" if file.exists(f) then dofile(f) end
f= "web_srv2.lua" if file.exists(f) then dofile(f) end

View File

@@ -0,0 +1,22 @@
-- Scripts à charger après le boot pour démarrer son appli
print("\n boot2.lua zf190917.0030 \n")
second_chance=nil
function heartbeat()
f= "flash_led_xfois.lua" if file.exists(f) then dofile(f) end
flash_led_xfois()
boottimer1=tmr.create()
boottimer1:alarm(1*1000, tmr.ALARM_AUTO, function()
xfois =2
blink_LED ()
end)
end
f= "0_get_data.lua" if file.exists(f) then dofile(f) end
f= "0_send_data.lua" if file.exists(f) then dofile(f) end
f= "0_cron.lua" if file.exists(f) then dofile(f) end
f=nil
heartbeat=nil
--heartbeat()

View File

@@ -0,0 +1,39 @@
-- programme pour faire clignoter x fois une LED avec un rapport on/off
function flash_led_xfois()
print("\n flash_led_xfois.lua zf190601.1618 \n")
--zLED=0 --NodeMCU
zLED=4 --EPS-M3
zTm_On_LED = 50 --> en ms
zTm_Off_LED = 100 --> en ms
nbfois = 0
gpio.write(zLED, gpio.HIGH)
gpio.mode(zLED, gpio.OUTPUT)
ztmr_Flash_LED = tmr.create()
function blink_LED ()
if nbfois >= xfois then
-- print(nbfois)
nbfois = 0
else
if gpio.read(zLED)==gpio.HIGH then
gpio.write(zLED, gpio.LOW)
-- tmr.alarm(ztmr_Flash_LED, zTm_Off_LED, tmr.ALARM_SINGLE, blink_LED)
ztmr_Flash_LED:alarm(zTm_Off_LED, tmr.ALARM_SINGLE, blink_LED)
else
gpio.write(zLED, gpio.HIGH)
nbfois = nbfois+1
-- tmr.alarm(ztmr_Flash_LED, zTm_On_LED, tmr.ALARM_SINGLE, blink_LED)
ztmr_Flash_LED:alarm(zTm_On_LED, tmr.ALARM_SINGLE, blink_LED)
end
end
end
-- xfois =2
-- blink_LED ()
end

View File

@@ -0,0 +1,63 @@
--Script de bootstrap, test au moment du boot qui a été la cause de boot.
-- Si la cause est un power on ou une connexion depuis l'IDE, alors
-- le script repair.lua pendant xx secondes avant de continuer
--Source: https://nodemcu.readthedocs.io/en/master/en/modules/node/#nodebootreason
print("\n init.lua zf190917.0001 \n")
zswitch=3 --switch flash
gpio.mode(zswitch, gpio.INT, gpio.PULLUP)
function hvbouton()
gpio.trig(zswitch, "none")
initalarme:unregister() initalarme2:unregister()
f= "boot.lua" if file.exists(f) then dofile(f) end
f= "boot2.lua" if file.exists(f) then dofile(f) end
end
gpio.trig(zswitch, "both", hvbouton)
function second_chance()
print("seconde chance...")
f= "repair.lua" if file.exists(f) then dofile(f) end
initalarme=tmr.create()
initalarme:alarm(4*1000, tmr.ALARM_SINGLE, function()
f= "boot.lua" if file.exists(f) then dofile(f) end
end)
initalarme2=tmr.create()
initalarme2:alarm(30*1000, tmr.ALARM_SINGLE, function()
gpio.trig(zswitch)
hvbouton=nil
zswitch=nil
reset_reason=nil
f= "boot2.lua" if file.exists(f) then dofile(f) end
end)
end
_, reset_reason = node.bootreason()
print("reset_reason:",reset_reason)
if reset_reason == 0 then
print("power on")
second_chance()
elseif reset_reason == 4 then
print("node.restart")
gpio.trig(zswitch)
hvbouton=nil
second_chance=nil
zswitch=nil
reset_reason=nil
f= "boot.lua" if file.exists(f) then dofile(f) end
f= "boot2.lua" if file.exists(f) then dofile(f) end
elseif reset_reason == 5 then
print("dsleep wake up")
f= "boot.lua" if file.exists(f) then dofile(f) end
f= "boot2.lua" if file.exists(f) then dofile(f) end
elseif reset_reason == 6 then
print("external reset")
second_chance()
else
print("autre raison")
second_chance()
end

View File

@@ -0,0 +1,373 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
version = "0.6.5 zf191020.1804"
print("luatool.py ver " + version)
#Améliorations
# Pour voir les améliorations il faut 'chercher' les zzz
#
# ESP8266 luatool
# Author e-mail: 4ref0nt@gmail.com
# Site: http://esp8266.ru
# Contributions from: https://github.com/sej7278
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA 02110-1301 USA.
import sys
import serial
from time import sleep
import socket
import argparse
from os.path import basename
tqdm_installed = True
try:
from tqdm import tqdm
except ImportError, e:
if e.message == 'No module named tqdm':
tqdm_installed = False
else:
raise
class TransportError(Exception):
"""Custom exception to represent errors with a transport
"""
def __init__(self, message):
self.message = message
def __str__(self):
return self.message
class AbstractTransport:
def __init__(self):
raise NotImplementedError('abstract transports cannot be instantiated.')
def close(self):
raise NotImplementedError('Function not implemented')
def read(self, length):
raise NotImplementedError('Function not implemented')
def writeln(self, data, check=1):
raise NotImplementedError('Function not implemented')
def writer(self, data):
self.writeln("file.writeline([==[" + data + "]==])\r")
def performcheck(self, expected):
line = ''
char = ''
i = -1
while char != chr(62): # '>'
char = self.read(1)
if char == '':
raise Exception('No proper answer from MCU')
if char == chr(13) or char == chr(10): # LF or CR
if line != '':
line = line.strip()
if line+'\r' == expected and not args.bar:
sys.stdout.write(" -> ok")
elif line+'\r' != expected:
if line[:4] == "lua:":
sys.stdout.write("\r\n\r\nLua ERROR: %s" % line)
raise Exception('ERROR from Lua interpreter\r\n\r\n')
else:
expected = expected.split("\r")[0]
sys.stdout.write("\r\n\r\nERROR")
sys.stdout.write("\r\n send string : '%s'" % expected)
sys.stdout.write("\r\n expected echo : '%s'" % expected)
sys.stdout.write("\r\n but got answer : '%s'" % line)
sys.stdout.write("\r\n\r\n")
raise Exception('Error sending data to MCU\r\n\r\n')
line = ''
else:
line += char
if char == chr(62) and expected[i] == char:
char = ''
i += 1
class SerialTransport(AbstractTransport):
def __init__(self, port, baud, delay):
self.port = port
self.baud = baud
self.serial = None
self.delay = delay
try:
self.serial = serial.Serial(port, baud)
except serial.SerialException as e:
raise TransportError(e.strerror)
self.serial.timeout = 3
self.serial.interCharTimeout = 3
# zzz191020 Il faut faire une pause juste après l'ouverture du port série
sleep(0.5)
def writeln(self, data, check=1):
# zzz191020 une petite pause après l'envoi de chaque ligne
sleep(self.delay)
if self.serial.inWaiting() > 0:
self.serial.flushInput()
if len(data) > 0 and not args.bar:
sys.stdout.write("\r\n->")
sys.stdout.write(data.split("\r")[0])
self.serial.write(data)
if check > 0:
self.performcheck(data)
elif not args.bar:
sys.stdout.write(" -> send without check")
def read(self, length):
return self.serial.read(length)
def close(self):
self.serial.flush()
self.serial.close()
class TcpSocketTransport(AbstractTransport):
def __init__(self, host, port):
self.host = host
self.port = port
self.socket = None
try:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error as e:
raise TransportError(e.strerror)
try:
self.socket.connect((host, port))
except socket.error as e:
raise TransportError(e.strerror)
# read intro from telnet server (see telnet_srv.lua)
self.socket.recv(50)
def writeln(self, data, check=1):
if len(data) > 0 and not args.bar:
sys.stdout.write("\r\n->")
sys.stdout.write(data.split("\r")[0])
self.socket.sendall(data)
if check > 0:
self.performcheck(data)
elif not args.bar:
sys.stdout.write(" -> send without check")
def read(self, length):
return self.socket.recv(length)
def close(self):
self.socket.close()
def decidetransport(cliargs):
if cliargs.ip:
data = cliargs.ip.split(':')
host = data[0]
if len(data) == 2:
port = int(data[1])
else:
port = 23
return TcpSocketTransport(host, port)
else:
return SerialTransport(cliargs.port, cliargs.baud, cliargs.delay)
if __name__ == '__main__':
# parse arguments or use defaults
parser = argparse.ArgumentParser(description='ESP8266 Lua script uploader.')
parser.add_argument('-p', '--port', default='/dev/ttyUSB0', help='Device name, default /dev/ttyUSB0')
# parser.add_argument('-b', '--baud', default=9600, help='Baudrate, default 9600')
parser.add_argument('-b', '--baud', default=115200, help='Baudrate, default 115200')
parser.add_argument('-f', '--src', default='main.lua', help='Source file on computer, default main.lua')
parser.add_argument('-t', '--dest', default=None, help='Destination file on MCU, default to source file name')
parser.add_argument('-c', '--compile', action='store_true', help='Compile lua to lc after upload')
parser.add_argument('-r', '--restart', action='store_true', help='Restart MCU after upload')
parser.add_argument('-d', '--dofile', action='store_true', help='Run the Lua script after upload')
parser.add_argument('-v', '--verbose', action='store_true', help="Show progress messages.")
parser.add_argument('-a', '--append', action='store_true', help='Append source file to destination file.')
parser.add_argument('-l', '--list', action='store_true', help='List files on device')
parser.add_argument('-w', '--wipe', action='store_true', help='Delete all lua/lc files on device.')
parser.add_argument('-i', '--id', action='store_true', help='Query the modules chip id.')
parser.add_argument('-e', '--echo', action='store_true', help='Echo output of MCU until script is terminated.')
parser.add_argument('--bar', action='store_true', help='Show a progress bar for uploads instead of printing each line')
parser.add_argument('--delay', default=0.03, help='Delay in seconds between each write, default 0.03 sec.', type=float)
parser.add_argument('--delete', default=None, help='Delete a lua/lc file from device.')
parser.add_argument('--ip', default=None, help='Connect to a telnet server on the device (--ip IP[:port])')
args = parser.parse_args()
transport = decidetransport(args)
if args.bar and not tqdm_installed:
sys.stdout.write("You must install the tqdm library to use the bar feature\n")
sys.stdout.write("To install, at the prompt type: \"pip install tqdm\"\n")
sys.exit(0)
if args.list:
#zzz191020 Amélioré la sortie du listing des fichiers
transport.writeln("print('\\n-----');local l = file.list();for k,v in pairs(l) do print(k..', size:'..v)end;print('-----\\n')\r", 0)
while True:
char = transport.read(1)
if char == '' or char == chr(62):
break
sys.stdout.write(char)
sys.exit(0)
if args.id:
transport.writeln("=node.chipid()\r", 0)
id=""
while True:
char = transport.read(1)
if char == '' or char == chr(62):
break
if char.isdigit():
id += char
print("\n"+id)
sys.exit(0)
if args.wipe:
transport.writeln("local l = file.list();for k,v in pairs(l) do print(k)end\r", 0)
file_list = []
fn = ""
while True:
char = transport.read(1)
if char == '' or char == chr(62):
break
if char not in ['\r', '\n']:
fn += char
else:
if fn:
file_list.append(fn.strip())
fn = ''
for fn in file_list[1:]: # first line is the list command sent to device
if args.verbose:
sys.stderr.write("Delete file {} from device.\r\n".format(fn))
transport.writeln("file.remove(\"" + fn + "\")\r")
sys.exit(0)
if args.delete:
transport.writeln("file.remove(\"" + args.delete + "\")\r")
sys.exit(0)
if args.dest is None:
args.dest = basename(args.src)
# open source file for reading
try:
try:
f = open(args.src, "rt")
except:
import os
base_dir = os.path.dirname(os.path.realpath(__file__))
f = open(os.path.join(base_dir, args.src), "rt")
os.chdir(base_dir)
except:
sys.stderr.write("Could not open input file \"%s\"\n" % args.src)
sys.exit(1)
# Verify the selected file will not exceed the size of the serial buffer.
# The size of the buffer is 256. This script does not accept files with
# lines longer than 230 characters to have some room for command overhead.
num_lines = 0
for ln in f:
if len(ln) > 230:
sys.stderr.write("File \"%s\" contains a line with more than 240 "
"characters. This exceeds the size of the serial buffer.\n"
% args.src)
f.close()
sys.exit(1)
num_lines += 1
# Go back to the beginning of the file after verifying it has the correct
# line length
f.seek(0)
# set serial timeout
if args.verbose:
sys.stderr.write("Upload starting\r\n")
# remove existing file on device
if args.append==False:
if args.verbose:
sys.stderr.write("Stage 1. Deleting old file from flash memory")
transport.writeln("file.open(\"" + args.dest + "\", \"w\")\r")
transport.writeln("file.close()\r")
transport.writeln("file.remove(\"" + args.dest + "\")\r")
else:
if args.verbose:
sys.stderr.write("[SKIPPED] Stage 1. Deleting old file from flash memory [SKIPPED]")
# read source file line by line and write to device
if args.verbose:
sys.stderr.write("\r\nStage 2. Creating file in flash memory and write first line")
if args.append:
transport.writeln("file.open(\"" + args.dest + "\", \"a+\")\r")
else:
transport.writeln("file.open(\"" + args.dest + "\", \"w+\")\r")
line = f.readline()
if args.verbose:
sys.stderr.write("\r\nStage 3. Start writing data to flash memory...")
if args.bar:
for i in tqdm(range(0, num_lines)):
transport.writer(line.strip())
line = f.readline()
else:
while line != '':
transport.writer(line.strip())
line = f.readline()
# close both files
f.close()
if args.verbose:
sys.stderr.write("\r\nStage 4. Flush data and closing file")
transport.writeln("file.flush()\r")
transport.writeln("file.close()\r")
# compile?
if args.compile:
if args.verbose:
sys.stderr.write("\r\nStage 5. Compiling")
transport.writeln("node.compile(\"" + args.dest + "\")\r")
transport.writeln("file.remove(\"" + args.dest + "\")\r")
# restart or dofile
if args.restart:
transport.writeln("node.restart()\r")
if args.dofile: # never exec if restart=1
transport.writeln("dofile(\"" + args.dest + "\")\r", 0)
if args.echo:
if args.verbose:
sys.stderr.write("\r\nEchoing MCU output, press Ctrl-C to exit")
while True:
sys.stdout.write(transport.read(1))
# close serial port
transport.close()
# flush screen
sys.stdout.flush()
sys.stderr.flush()
if not args.bar:
sys.stderr.write("\r\n--->>> All done <<<---\r\n")

View File

@@ -0,0 +1,87 @@
-- Serveur telnet pour connexion en remote WIFI, NOUVELLE VERSION !
-- source: https://github.com/nodemcu/nodemcu-firmware/blob/master/lua_examples/telnet/telnet.lua
print("\n telnet_srv2.lua zf181215.1326 \n")
local node, table, tmr, wifi, uwrite, tostring =
node, table, tmr, wifi, uart.write, tostring
local function telnet_listener(socket)
local insert, remove, concat, heap, gc =
table.insert, table.remove, table.concat, node.heap, collectgarbage
local fifo1, fifo1l, fifo2, fifo2l = {}, 0, {}, 0
local s -- s is a copy of the TCP socket if and only if sending is in progress
local wdclr, cnt = tmr.wdclr, 0
local function debug(fmt, ...)
if (...) then fmt = fmt:format(...) end
uwrite(0, "\r\nDBG: ",fmt,"\r\n" )
cnt = cnt + 1
if cnt % 10 then wdclr() end
end
local function flushGarbage()
if heap() < 13440 then gc() end
end
local function sendLine()
if not s then return end
if fifo2l + fifo1l == 0 then -- both FIFOs empty, so clear down s
s = nil
return
end
flushGarbage()
if #fifo2 < 4 then -- Flush FIFO1 into FIFO2
insert(fifo2,concat(fifo1))
fifo2l, fifo1, fifo1l = fifo2l + fifo1l, {}, 0
end
local rec = remove(fifo2,1) .. (remove(fifo2,1) or '') ..
(remove(fifo2,1) or '') .. (remove(fifo2,1) or '')
fifo2l = fifo2l - #rec
flushGarbage()
s:send(rec)
end
local F1_SIZE = 256
local function queueLine(str)
while #str > 0 do -- this is because str might be longer than the packet size!
local k, l = F1_SIZE - fifo1l, #str
local chunk
if #fifo1 >= 32 or (k < l and k < 16) then
insert(fifo2, concat(fifo1))
fifo2l, fifo1, fifo1l, k = fifo2l + fifo1l, {}, 0, F1_SIZE
end
if l > k+16 then -- also tolerate a size overrun of 16 bytes to avoid a split
chunk, str = str:sub(1,k), str:sub(k+1)
else
chunk, str = str, ''
end
insert(fifo1, chunk)
fifo1l = fifo1l + #chunk
end
if not s and socket then
s = socket
sendLine()
else
flushGarbage()
end
end
local function receiveLine(s, line)
node.input(line)
end
local function disconnect(s)
fifo1, fifo1l, fifo2, fifo2l, s = {}, 0, {}, 0, nil
node.output(nil)
end
socket:on("receive", receiveLine)
socket:on("disconnection", disconnect)
socket:on("sent", sendLine)
node.output(queueLine, 0)
end
net.createServer(net.TCP, 180):listen(23, telnet_listener)
print("Telnet server running...\nUsage: telnet -rN ip\n")

View File

@@ -0,0 +1,10 @@
#!/bin/bash
# Petit script pour télécharger facilement tout le binz
#zf191020.1745
chmod +x luatool.py
./luatool.py --port /dev/cu.wchusbserial1410 -l
./luatool.py --port /dev/cu.wchusbserial1410 -f websocket.lua
./luatool.py --port /dev/cu.wchusbserial1410 -f main.lua
./luatool.py --port /dev/cu.wchusbserial1410 -f init.lua
./luatool.py --port /dev/cu.wchusbserial1410 -l

View File

@@ -0,0 +1,10 @@
-- Démarre le WIFI en mode AP
print("\n wifi_ap_stop.lua zf180824.2000 \n")
local zmodewifi=wifi.getmode()
if zmodewifi == wifi.SOFTAP then
wifi.setmode(wifi.NULLMODE)
elseif zmodewifi == wifi.STATIONAP then
wifi.setmode(wifi.STATION)
end
print("WIFI AP arrêté")

View File

@@ -0,0 +1,11 @@
-- Petit script pour configurer le client WIFI du NodeMCU
function wifi_cli_conf()
print("\n wifi_cli_conf.lua zf190726.1912 \n")
-- les secrets sont maintenant initialisés par boot.lua !
wifi.sta.config{ssid=cli_ssid, pwd=cli_pwd, save=true}
end
wifi_cli_conf()
wifi_cli_conf=nil

View File

@@ -0,0 +1,20 @@
-- Petit script pour connecter le NodeMCU sur un AP Wifi avec l'accompte sauvé en EEPROM
function wifi_cli_start()
print("\n wifi_cli_start.lua zf190310.1519 \n")
local zmodewifi=wifi.getmode()
if zmodewifi == wifi.NULLMODE then
print("WIFI mode CLI only")
wifi.setmode(wifi.STATION)
elseif zmodewifi == wifi.SOFTAP then
print("WIFI mode AP+CLI")
wifi.setmode(wifi.STATIONAP)
end
wifi.sta.autoconnect(1)
wifi.sta.connect()
--f= "wifi_get_ip.lua" if file.exists(f) then dofile(f) end
end
wifi_cli_start()
wifi_cli_start=nil

View File

@@ -0,0 +1,33 @@
-- Petit script pour afficher les infos actuel du WIFI
print("\n wifi_info.lua zf190727.1220 \n")
local zmodewifi=wifi.getmode()
--wifi.NULLMODE, wifi.STATION, wifi.SOFTAP, wifi.STATIONAP
if zmodewifi == wifi.NULLMODE then
print("WIFI OFF")
elseif zmodewifi == wifi.STATION then
print("WIFI mode CLI")
print("Connected IP:\n",wifi.sta.getip())
local sta_config=wifi.sta.getconfig(true)
print("Current client config:")
print("\tssid:", sta_config.ssid)
print("\tpassword:", sta_config.pwd)
print("\tbssid:", sta_config.bssid)
elseif zmodewifi == wifi.SOFTAP then
print("WIFI mode AP")
print("AP MAC:\n",wifi.ap.getmac())
print("AP IP:\n",wifi.ap.getip())
print("AP Connect:\n",wifi.ap.getconfig())
elseif zmodewifi == wifi.STATIONAP then
print("WIFI mode CLI+AP")
print("Connected IP:\n",wifi.sta.getip())
local sta_config=wifi.sta.getconfig(true)
print("Current client config:")
print("\tssid:", sta_config.ssid)
print("\tpassword:", sta_config.pwd)
print("\tbssid:", sta_config.bssid)
print("AP MAC: ", wifi.ap.getmac())
print("AP IP: ", wifi.ap.getip())
end