Nouveau projet solar-grafana
14
Mesures/humidity/solar-grafana/00test_cmd.lua
Normal file
@@ -0,0 +1,14 @@
|
||||
print("getpeer",srv_rt:getpeer())
|
||||
print("srv_rt",srv_rt)
|
||||
srv_rt=nil
|
||||
rt_connect=nil
|
||||
telnet_listener=nil
|
||||
package=nil
|
||||
d=nil
|
||||
require=nil
|
||||
pairs=nil
|
||||
ipairs=nil
|
||||
telnet_listener=nil
|
||||
|
||||
rt_retry=3
|
||||
rt_connect()
|
||||
27
Mesures/humidity/solar-grafana/0_btn_flipflop.lua
Normal file
@@ -0,0 +1,27 @@
|
||||
-- Petit scripts pour faire un flip flop avec le bouton et la led du nodemcu
|
||||
-- Très intéressant la techno utilisée ici pour enlever les rebonds du micro switch
|
||||
-- dans la variable b se trouve l'heure à laquelle l'interruption est arrivée, il suffit juste alors de lui mettre un petit délai de 300mS
|
||||
|
||||
print("\n 0_btn_flipflop.lua zf200216.1457 \n")
|
||||
|
||||
gpio.write(zLED,1) gpio.mode(zLED,gpio.OUTPUT)
|
||||
gpio.mode(zBTN,gpio.INT)
|
||||
|
||||
d=tmr.now()
|
||||
|
||||
function zled (a,b,c)
|
||||
--print("a: "..a..",b: "..b..",c: "..c)
|
||||
if b-d > 300*1000 then
|
||||
if verbose then
|
||||
gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH)
|
||||
verbose=false
|
||||
else
|
||||
gpio.write(zLED, gpio.LOW) tmr.delay(200000) gpio.write(zLED, gpio.HIGH)
|
||||
verbose=true
|
||||
end
|
||||
d=b
|
||||
print("verbose:",verbose)
|
||||
end
|
||||
end
|
||||
|
||||
gpio.trig(zBTN, "down", zled)
|
||||
24
Mesures/humidity/solar-grafana/0_cron.lua
Normal file
@@ -0,0 +1,24 @@
|
||||
-- Petit script pour faire office de crontab pour les mesures
|
||||
print("\n 0_cron.lua zf200229.1557 \n")
|
||||
|
||||
cron1=tmr.create()
|
||||
cron1:alarm(60*1000, tmr.ALARM_AUTO, function()
|
||||
if verbose then print("cron1........................") end
|
||||
if verbose then gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH) end
|
||||
|
||||
f = "0_zdyndns.lua" if file.exists(f) then dofile(f) end
|
||||
|
||||
--[[
|
||||
f = "0_htu21d.lua" if file.exists(f) then dofile(f) end
|
||||
|
||||
zurl = thingspeak_url.."field1="..tostring(ztemp1).."&field2="..tostring(zhum1)
|
||||
|
||||
f = "0_send_data.lua" if file.exists(f) then dofile(f) end
|
||||
|
||||
ztemp1=nil zhum1=nil
|
||||
]]
|
||||
|
||||
if verbose then print(node.heap()) end
|
||||
collectgarbage()
|
||||
if verbose then print(node.heap()) end
|
||||
end)
|
||||
43
Mesures/humidity/solar-grafana/0_htu21d.lua
Normal file
@@ -0,0 +1,43 @@
|
||||
-- Lit le capteur I2C HTU21D de mesure d'humidité et de température
|
||||
-- https://github.com/zuzu59/NodeMCU_Lua/tree/master/Mesures/humidity/bolo-thingspeak/docu/HTU21D.txt
|
||||
|
||||
function readHTU21D()
|
||||
if verbose then print("\n 0_htu21d.lua zf200119.1517 \n") end
|
||||
|
||||
id = 0 sda = 5 scl = 6 addr = 0x40
|
||||
HUMIDITY = 0xE5 TEMPERATURE = 0xE3
|
||||
i2c.setup(id, sda, scl, i2c.SLOW) sda = nil scl = nil
|
||||
|
||||
function read_HTU21D(zreg, zdelay)
|
||||
i2c.start(id) i2c.address(id, addr, i2c.TRANSMITTER)
|
||||
i2c.write(id, zreg) i2c.stop(id)
|
||||
i2c.start(id) i2c.address(id, addr, i2c.RECEIVER)
|
||||
tmr.delay(zdelay)
|
||||
r = i2c.read(id,3) i2c.stop(id)
|
||||
return r
|
||||
end
|
||||
|
||||
function readTemp()
|
||||
r = read_HTU21D(TEMPERATURE, 50000)
|
||||
r = (bit.band((bit.lshift(string.byte(r,1),8)+string.byte(r,2)),0xfffc)*17572)/65536-4685
|
||||
return tonumber(string.format("%.1f", tostring(r/100)))
|
||||
end
|
||||
|
||||
function readHumi()
|
||||
r = read_HTU21D(HUMIDITY, 16000)
|
||||
r = (bit.band((bit.lshift(string.byte(r,1),8)+string.byte(r,2)),0xfffc)*12500)/65536-600
|
||||
return tonumber(string.format("%.1f", tostring(r/100)))
|
||||
end
|
||||
|
||||
ztemp1=readTemp() zhum1=readHumi()
|
||||
if verbose then print("Temperature: "..ztemp1.." °C") end
|
||||
if verbose then print("Humidity: "..zhum1.." %") end
|
||||
|
||||
id=nil sda=nil scl=nil addr=nil HUMIDITY=nil TEMPERATURE=nil r=nil
|
||||
read_HTU21D=nil readTemp=nil readHumi=nil readHTU21D=nil
|
||||
if verbose then print(node.heap()) end
|
||||
collectgarbage()
|
||||
if verbose then print(node.heap()) end
|
||||
end
|
||||
|
||||
readHTU21D()
|
||||
24
Mesures/humidity/solar-grafana/0_send_data.lua
Normal file
@@ -0,0 +1,24 @@
|
||||
-- Petit script pour envoyer les valeurs de température sur un serveur WEB via un HTTP GET
|
||||
|
||||
function send_data()
|
||||
if verbose then print("\n 0_send_data.lua zf200119.1518 \n") end
|
||||
|
||||
if verbose then print("send_data_web: ") end
|
||||
if verbose then print(zurl) end
|
||||
|
||||
http.get(zurl, nil, function(code, data)
|
||||
if (code < 0) then
|
||||
if verbose then print("HTTP request failed") end
|
||||
if verbose then print("zuzu", code, data) end
|
||||
else
|
||||
if verbose then print(code, data) end
|
||||
end
|
||||
zurl=nil
|
||||
end)
|
||||
zurl=nil send_data=nil
|
||||
if verbose then print(node.heap()) end
|
||||
collectgarbage()
|
||||
if verbose then print(node.heap()) end
|
||||
end
|
||||
|
||||
send_data()
|
||||
182
Mesures/humidity/solar-grafana/0_tst3_socat.lua
Normal file
@@ -0,0 +1,182 @@
|
||||
--[[
|
||||
tests connection reverse telnet
|
||||
commande à faire tourner sur le serveur
|
||||
|
||||
1ere console
|
||||
pour une liaison directe:
|
||||
socat TCP-LISTEN:23047,fork,reuseaddr STDIO
|
||||
pour une console sur un port:
|
||||
socat TCP-LISTEN:23047,reuseaddr,fork TCP-LISTEN:23000,reuseaddr,bind=127.0.0.1
|
||||
|
||||
2e console
|
||||
telnet -r localhost 23000
|
||||
]]
|
||||
|
||||
print("\n 0_tst3_socat.lua zf200229.2243 \n")
|
||||
|
||||
local node, table, tmr, uwrite, tostring =
|
||||
node, table, tmr, 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
|
||||
fifo1, fifo1l, fifo2, fifo2l, s = nil, nil, nil, nil, nil
|
||||
--insert, remove, concat, heap, gc = nil, nil, nil, nil, nil
|
||||
--wdclr, cnt = nil, nil
|
||||
node.output(nil)
|
||||
print("disconnected...")
|
||||
-- print("rt_retry:",rt_retry)
|
||||
-- rt_retry=rt_retry-1
|
||||
-- print("rt_retry:",rt_retry)
|
||||
-- if rt_retry>=0 then
|
||||
print("on ressaie en vitesse une fois ;-)")
|
||||
rt_connect()
|
||||
-- end
|
||||
end
|
||||
|
||||
--zzz
|
||||
local function zconnection(s)
|
||||
print("Welcome on ne devrait jamais passer par là to NodeMCU world.")
|
||||
end
|
||||
|
||||
socket:on("connection", zconnection)
|
||||
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("Revers telnet server running...\n")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function rt_connect()
|
||||
if verbose then
|
||||
gpio.write(zLED, gpio.HIGH)
|
||||
print("trying connect to "..console_host..":"..console_port)
|
||||
print(node.heap()) collectgarbage() print(node.heap())
|
||||
end
|
||||
srv_rt = nil srv_rt = net.createConnection(net.TCP, 0)
|
||||
srv_rt:on("connection", function(sck)
|
||||
if verbose then
|
||||
print("connected on "..console_host..":"..console_port)
|
||||
print(node.heap()) collectgarbage() print(node.heap())
|
||||
end
|
||||
telnet_listener(sck)
|
||||
print("Welcome to NodeMCU world.")
|
||||
end)
|
||||
srv_rt:connect(console_port,console_host)
|
||||
end
|
||||
|
||||
tmr_socat1=tmr.create()
|
||||
tmr_socat1:alarm(5*1000, tmr.ALARM_AUTO , function()
|
||||
rt_retry=1
|
||||
if verbose then gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH) end
|
||||
|
||||
if srv_rt~=nil then
|
||||
if console_port == srv_rt:getpeer() then
|
||||
--cela tourne...
|
||||
if verbose then gpio.write(zLED, gpio.LOW) end
|
||||
else
|
||||
--on relance...
|
||||
rt_connect()
|
||||
end
|
||||
else
|
||||
--on relance...
|
||||
rt_connect()
|
||||
end
|
||||
end)
|
||||
|
||||
rt_retry=3
|
||||
rt_connect()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--[[
|
||||
tmr_socat1:unregister()
|
||||
for k,v in pairs(_G) do print(k,v) end
|
||||
|
||||
print(srv_rt:getpeer())
|
||||
|
||||
srv_rt:connect(console_port,console_host)
|
||||
|
||||
gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH)
|
||||
if console_port == srv_rt:getpeer() then
|
||||
gpio.write(zLED, gpio.LOW)
|
||||
else
|
||||
gpio.write(zLED, gpio.HIGH)
|
||||
end
|
||||
|
||||
|
||||
]]
|
||||
31
Mesures/humidity/solar-grafana/0_tst_maxime.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
-- tests pour Maxime pour envoyer une valeur sur Thingspeak en pressant le bouton
|
||||
-- ATTENTION: ce n'est pas testé
|
||||
-- zf200131.1124
|
||||
|
||||
|
||||
zBTN=3
|
||||
gpio.mode(zBTN,gpio.INT)
|
||||
|
||||
d=tmr.now()
|
||||
|
||||
function maxime_send (a,b,c)
|
||||
if b-d > 300*1000 then
|
||||
ztemp1=ta valeur
|
||||
zhum1= une autre valeur
|
||||
thingspeak_url="http://api.thingspeak.com/update?api_key=kkk&"
|
||||
zurl = thingspeak_url.."field1="..tostring(ztemp1).."&field2="..tostring(zhum1)
|
||||
|
||||
http.get(zurl, nil, function(code, data)
|
||||
if (code < 0) then
|
||||
if verbose then print("HTTP request failed") end
|
||||
if verbose then print("zuzu", code, data) end
|
||||
else
|
||||
if verbose then print(code, data) end
|
||||
end
|
||||
end)
|
||||
|
||||
d=b
|
||||
end
|
||||
end
|
||||
|
||||
gpio.trig(zBTN, "down", maxime_send)
|
||||
33
Mesures/humidity/solar-grafana/0_zdyndns.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
-- Petit script pour s'inregistrer sur zdyndns
|
||||
|
||||
function send_zdyndns()
|
||||
if verbose then print("\n 0_zdyndns.lua zf200229.1553 \n") end
|
||||
|
||||
zip = wifi.sta.getip()
|
||||
zdyndns_str = "s "..node_id..","..console_host..":"..tostring(console_port).." "..zip.."\n"
|
||||
if verbose then print("zdyndns_str: /"..zdyndns_str.."/") end
|
||||
|
||||
srv_zdyndns = net.createConnection(net.TCP, 0)
|
||||
|
||||
srv_zdyndns:on("receive", function(conn, pl)
|
||||
print("receiving...")
|
||||
print(pl)
|
||||
end)
|
||||
|
||||
srv_zdyndns:on("connection", function(sck)
|
||||
if verbose then print("connected & sending...") end
|
||||
sck:send(zdyndns_str, function(sk)
|
||||
sk:close()
|
||||
if verbose then print("close...") end
|
||||
zdyndns_str=nil zip=nil srv_zdyndns=nil send_zdyndns=nil
|
||||
if verbose then print(node.heap()) end
|
||||
collectgarbage()
|
||||
if verbose then print(node.heap()) end
|
||||
end)
|
||||
end)
|
||||
|
||||
srv_zdyndns:connect(zdyndns_port,zdyndns_host)
|
||||
|
||||
end
|
||||
|
||||
send_zdyndns()
|
||||
313
Mesures/humidity/solar-grafana/README.md
Normal file
@@ -0,0 +1,313 @@
|
||||
# Mesure de température et d'humidité avec un NodeMCU en Lua
|
||||
zf200216.1231
|
||||
|
||||
Petit projet pour mesurer la température et l'humidité avec un capteur HTU21D et l'afficher sur ThingSpeak. Comme par exemple pour *enregistrer* la température et l'humidité d'un local au cours du temps.
|
||||
|
||||
<br><br>
|
||||
|
||||
Exemple de sortie sur ThingSpeak
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
Constellation de sondes de mesures
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
Montage du capteur HTU21D directement sur le NodeMCU, chose à ne PAS faire, car la température du NodeMCU fausse complètement les mesures d'humidité !
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
Montage correct du capteur HTU21D en *déporté* sur le NodeMCU
|
||||
|
||||
|
||||
|
||||
## Autres utilisations de ce projet
|
||||
|
||||
On peut très bien *enregistrer* d'autres *mesures* comme par exemple, une consommation électrique, production solaire ou débit d'eau d'une douche. Il y a très peu de lignes à modifier pour le faire. C'est donc la base de l'enregistrement pour pleins de mesures en domotique ;-)
|
||||
|
||||
|
||||
|
||||
<br><br>
|
||||
## Avantages de travailler avec langage interprété (Lua) VS compilé (Arduino C++)
|
||||
|
||||
On peut voir ici, avec ce projet assez complet, toutes les possibilités offertes de la programmation d'un NodeMCU en LUA, en mode événementiel. <br>
|
||||
Choses qui ne seraient pas possible si on l'avait fait en C++ (mode Arduino), comme par exemple:
|
||||
|
||||
* configuration du WIFI via une page WEB servie par le NodeMCU (pas besoin de brancher un interface USB/TTL)
|
||||
* serveur WEB *Active Server Pages ZYX*, permet de faire des pages HTML *dynamiques* avec du code LUA *in line*. Les pages HTML sont *sauvées* dans le système de fichiers de la FLASH du NodeMCU et *interprétées au vol* lors de la *lecture*
|
||||
* serveur WEB pour l'affichage de l'humidité et de la température
|
||||
* mini WEB IDE, modification du code source en remote directement depuis une page WEB, pas besoin d'IDE
|
||||
* serveur TELNET, utilisation de la console en remote pour le dépannage (mise à jour du code centralisée)
|
||||
* crontab, horloge pour les mesures
|
||||
|
||||
Toutes les fonctions sont bien séparées dans des scripts .lua, cela *complexifie* le projet mais cela facilite la portabilité entre les projets et aussi sa mise au point.
|
||||
|
||||
|
||||
## Principes de mesures
|
||||
|
||||
On utilise un tout petit capteur low cost, le **HTU21D**, mesure de température et d'humidité sur bus I2C.
|
||||
|
||||
https://www.aliexpress.com/item/32480177429.html
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
Il est vraiment très bon marché (1.5$), simple à utiliser et super précis.
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
Incroyable la résolution de la mesure ! On peut observer ici l'arrivée le matin au salon, l'ouverture de la porte de la salle de bain après avoir pris la douche et l'ouverture de la fenêtre. Tout ceci dans la résolution de 1 à 3% de l'humidité relative
|
||||
|
||||
|
||||
Présentation:
|
||||
|
||||
https://learn.sparkfun.com/tutorials/htu21d-humidity-sensor-hookup-guide/all
|
||||
|
||||
|
||||
Datasheet:
|
||||
|
||||
https://cdn.sparkfun.com/assets/6/a/8/e/f/525778d4757b7f50398b4567.pdf
|
||||
|
||||
|
||||
### Schéma
|
||||
|
||||
<br><br>
|
||||
|
||||
Schéma de connexion à 4x fils très simple
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
Et son PCB (bread board)
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
Banc test de Mesures
|
||||
|
||||
|
||||
## Le cloud ThingSpeak
|
||||
|
||||
ThingSpeak est un service de plateforme d'analyse IoT qui vous permet d'agréger, de visualiser et d'analyser des flux de données en direct dans le cloud. Vous pouvez envoyer des données à ThingSpeak depuis vos appareils, créer une visualisation instantanée des données en direct et envoyer des alertes.
|
||||
|
||||
La version gratuite nous permet de faire:
|
||||
|
||||
* envoi de 3'000'000 de message par an, soit environ 8'200 messages par jour
|
||||
* intervalle d'envoi entre deux messages est d'au minimum de 15 secondes
|
||||
* 4x canaux à disposition
|
||||
* 3x connexion simultanées au MQTT
|
||||
* 3x partages de canaux privés
|
||||
|
||||
Ce qui est amplement suffisant pour débuter avec l'IoT dans le Cloud et savoir ce que l'on veut faire par la suite ;-)
|
||||
|
||||
La version payante est assez chère, comme toutes les autres du reste :-(
|
||||
|
||||
|
||||
## Parties principales du code
|
||||
Le corps du projet se trouve dans ces 4x fichiers !
|
||||
|
||||
* secrets_project.lua
|
||||
* 0_htu21d.lua
|
||||
* 0_send_data.lua
|
||||
* 0_cron.lua
|
||||
|
||||
|
||||
### Les secrets du projet
|
||||
|
||||
Dans ce fichier se trouvent les *secrets* du projet qui ne doivent pas se retrouver sur GitHub, mais qui peuvent aussi être différents si on *duplique* son projet dans différents *lieux* (mesure à Lausanne et Renens par exemple).
|
||||
|
||||
```
|
||||
if node.chipid() == 6734851 then node_id = "sonoff_1" zLED=7 end
|
||||
if node.chipid() == 16110605 then node_id = "sonoff_2" zLED=7 end
|
||||
if node.chipid() == 3049119 then node_id = "adc_1" end
|
||||
if node.chipid() == 3048906 then
|
||||
node_id = "bolo_1"
|
||||
thingspeak_url="http://api.thingspeak.com/update?api_key=kkk&"
|
||||
end
|
||||
if node.chipid() == 3049014 then
|
||||
node_id = "tst_temp_1"
|
||||
thingspeak_url="http://api.thingspeak.com/update?api_key=kkk&"
|
||||
end
|
||||
```
|
||||
|
||||
C'est ici que l'on met l'*url* avec son *token* utilisé par *ThingSpeak*
|
||||
ThingSpeak
|
||||
|
||||
On met aussi ici l'*identification* du NodeMCU de la mesure afin de pouvoir reconnaitre les différents *points* de mesure dans un même lieu. Chaque NodeMCU à son *propre* numéro de *série* !
|
||||
|
||||
|
||||
### La mesure de température et d'humidité
|
||||
|
||||
On accède au capteur de mesure de température et d'humidité HTU21D très simplement (pas besoin de lib) au moyen de commandes de base I2C:
|
||||
|
||||
i2c.start, i2c.stop, i2c.address, i2c.write, i2c.read
|
||||
|
||||
```
|
||||
function read_HTU21D(zreg, zdelay)
|
||||
i2c.start(id) i2c.address(id, addr, i2c.TRANSMITTER)
|
||||
i2c.write(id, zreg) i2c.stop(id)
|
||||
i2c.start(id) i2c.address(id, addr, i2c.RECEIVER)
|
||||
tmr.delay(zdelay)
|
||||
r = i2c.read(id,3) i2c.stop(id)
|
||||
return r
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
### L'envoi des mesures dans le Cloud ThingSpeak
|
||||
|
||||
Les données de mesures sont simplement envoyées sur ThingSpeak au moyen d'une *requête* HTML de type *GET*:
|
||||
|
||||
On peut le faire directement depuis son browser pour des tests par exemple: envoi des valeurs température de 12˚ et humidité 45%:
|
||||
|
||||
```
|
||||
https://api.thingspeak.com/update?api_key=kkk&field1=12&field1=45
|
||||
```
|
||||
|
||||
Construction de l'url d'envoi en Lua:
|
||||
|
||||
```
|
||||
zurl=thingspeak_url.."field1="..tostring(ztemp1).."&field2="..tostring(zhum1)
|
||||
send_temp()
|
||||
```
|
||||
|
||||
|
||||
### L'horloge des mesures
|
||||
|
||||
Finalement il faut *envoyer* au moyen d'un *timer* toutes les x secondes les mesures de températures au Cloud ThingSpeak
|
||||
|
||||
```
|
||||
cron1=tmr.create()
|
||||
cron1:alarm(20*1000, tmr.ALARM_AUTO, function()
|
||||
print("cron1........................")
|
||||
ztemp1=readTemp()
|
||||
zhum1=readHumi()
|
||||
print("Temperature: "..ztemp1.." °C")
|
||||
print("Humidity: "..zhum1.." %")
|
||||
zurl=thingspeak_url.."field1="..tostring(ztemp1).."&field2="..tostring(zhum1)
|
||||
send_temp()
|
||||
end)
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Il faut *flasher* le NodeMCU avec ce firmware:
|
||||
|
||||
https://github.com/zuzu59/NodeMCU_Lua/blob/master/Firmware/nodemcu-master-19-modules-2019-12-31-16-40-12-float.bin
|
||||
|
||||
Qui contient ces modules:
|
||||
```
|
||||
adc ads1115 bit enduser_setup file gpio http i2c mqtt net node ow rtctime sjson sntp tmr uart wifi ws2812
|
||||
```
|
||||
|
||||
C'est un firmware passe partout, il contient trop de modules pour ce projet mais qui est très pratique !
|
||||
|
||||
|
||||
|
||||
## Utilisation
|
||||
|
||||
|
||||
### Configuration du WIFI du NodeMCU_Lua
|
||||
L'accès au NodeMCU se fait via des pages WEB distribuée depuis son petit serveur WEB ASP (Active Server Pages) avec l'interprétation du code Lua inline au vol !
|
||||
|
||||
Lors du démarrage du NodeMCU il va chercher à se connecter sur le WIFI qu'il trouve dans sa configuration, fichier *eus_params.lua*. S'il n'y parvient pas au bout de 15 secondes, il va démarrer un petit serveur WIFI, **AP: NodeMCU_node_id**, on peut alors utiliser le NodeMCU sans avoir besoin d'une *connexion* Internet, mais bien entendu sans envoi de données dans le Cloud.
|
||||
|
||||
On se connecte alors avec un browser WEB sur l'adresse:
|
||||
|
||||
```
|
||||
http://192.168.4.1
|
||||
```
|
||||
|
||||
On choisit *Wifi setup* et enfin, au milieu de la page, on confirme l'action en cliquant sur *Ok* (ceci pour éviter que l'on bascule dans le mode setup WIFI par erreur).
|
||||
|
||||
Après quelques secondes un nouveau serveur WIFI va démarrer avec une procédure de configuration du WIFI du NodeMCU, **AP: Setup Gadget** xxx, on se connecte dessus avec son ordinateur pour aller à nouveau *voir* la page:
|
||||
|
||||
```
|
||||
http://192.168.4.1
|
||||
```
|
||||
|
||||
Après configuration du WIFI, l'adresse IP allouée au NodeMCU devrait apparaître en haut de la page.
|
||||
|
||||
Le NodeMCU redémarre et est prêt à envoyer les mesures sur le Cloud, s'il est configuré correctement pour le bon compte ThingSpeak !
|
||||
|
||||
|
||||
|
||||
### Configuration de ThingSpeak
|
||||
|
||||
Afin de pouvoir utiliser ThingSpeak, il faut *créé* un *channel*, le configurer pour lui indiquer que nous voulons deux champs (température et humidité) et surtout récupérer le token du channel pour le mettre dans le fichier *secrets_projet.lua*
|
||||
|
||||
|
||||
|
||||
### Visualisation des données dans ThingSpeak
|
||||
|
||||
On peut voir alors arriver, toutes les 20 secondes, les mesures de température et d'humidité sur ThingSpeak.
|
||||
|
||||
<br><br>
|
||||
Exemple de sortie sur ThingSpeak
|
||||
|
||||
On peut facilement modifier l'affichage des graphiques au moyen du petit *crayon* en haut à droite de chaque graphique
|
||||
|
||||
Très vite on va s'apercevoir qu'il faudra augmenter le temps entre chaque mesures, passer à 300 secondes au lieu de 20 secondes par exemple.
|
||||
|
||||
|
||||
|
||||
### Exportation des données en CSV depuis ThingSpeak
|
||||
|
||||
On peut très facilement exporter après coup les données du channel de ThingSpeak en CSV pour en faire un rapport dans un tableur par exemple.
|
||||
|
||||
|
||||
|
||||
### Distribution des rôles de NodeMCU
|
||||
|
||||
Comme on peut avoir plusieurs points de mesures à différents endroit dans le local, il n'y a qu'un seul fichier de *secrets*. C'est dans ce fichier, *secrets_projet.lua*, qu'il y a l'information de l'url de ThingSpeak ains que le token pour le bon channel !<br>
|
||||
|
||||
|
||||
|
||||
### Affichage des températures/humidité en local sur le NodeMCU
|
||||
|
||||
On peut lire la température et l'humidité directement sur le NodeMCU au moyen de cette url (il faut modifier l'adresse IP du NodeMCU en question):
|
||||
|
||||
```
|
||||
http://192.168.0.xxx/disp_temp.html
|
||||
```
|
||||
|
||||
|
||||
### Affichage du petit serveur web du NodeMCU_Lua
|
||||
|
||||
Chaque NodeMCU a son propre serveur WEB, on peut l'accéder simplement depuis son adresse IP:
|
||||
|
||||
```
|
||||
http://192.168.0.xxx
|
||||
```
|
||||
|
||||
|
||||
### Modification du code source du NodeMCU en remote
|
||||
|
||||
On peut directement modifier le code source Lua du NodeMCU en remote avec ce petit WEB IDE (il faut le *lancer* avant depuis la home page du NodeMCU !):
|
||||
|
||||
```
|
||||
http://192.168.0.xxx:88
|
||||
```
|
||||
|
||||
|
||||
### Utilisation de la console du NodeMCU en remote
|
||||
|
||||
Très pratique pour le debug, on peut accéder à la console du NodeMCU en remote avec telnet:
|
||||
|
||||
```
|
||||
telnet -r 192.168.0.xxx
|
||||
```
|
||||
|
||||
ou sur MAC
|
||||
|
||||
```
|
||||
telnet -rN 192.168.0.xxx
|
||||
```
|
||||
|
||||
C'est aussi depuis ce moyen que l'on peut mettre, à distance, à jour le code Lua du NodeMCU de manière centralisée et automatique (luatool.py)
|
||||
37
Mesures/humidity/solar-grafana/_secrets_project.lua_
Normal file
@@ -0,0 +1,37 @@
|
||||
-- Petit script pour configurer les secrets dans ce projet
|
||||
-- et que l'on n'aimerait pas être exportés sur Internet (github)
|
||||
-- Il faut donc modifier le .gitignore avec secrets*.lua
|
||||
-- il faut le renommer en 'secrets_project.lua' et sera exécuté
|
||||
-- par 'wifi_init.lua' au moment du boot
|
||||
|
||||
-- pour récupérer l'ID de son NodeMCU il faut faire:
|
||||
-- print(node.chipid())
|
||||
|
||||
|
||||
function secrets_project()
|
||||
print("\n secrets_project.lua zf200131.1058 \n")
|
||||
|
||||
zLED=4 -- NodeMCU
|
||||
--zLED=7 -- SonOff
|
||||
zBTN=3
|
||||
|
||||
node_id = "generic"
|
||||
if node.chipid() == 6734851 then node_id = "sonoff_1" zLED=7 end
|
||||
if node.chipid() == 16110605 then node_id = "sonoff_2" zLED=7 end
|
||||
if node.chipid() == 3049119 then node_id = "adc_1" end
|
||||
if node.chipid() == 3048906 then
|
||||
node_id = "bolo_1"
|
||||
thingspeak_url="http://api.thingspeak.com/update?api_key=kkk&"
|
||||
end
|
||||
if node.chipid() == 3049014 then
|
||||
node_id = "tst_temp_1"
|
||||
thingspeak_url="http://api.thingspeak.com/update?api_key=kkk&"
|
||||
end
|
||||
print("node_id: "..node_id)
|
||||
end
|
||||
secrets_project()
|
||||
secrets_project=nil
|
||||
|
||||
--[[
|
||||
=node.chipid()
|
||||
]]
|
||||
18
Mesures/humidity/solar-grafana/_secrets_wifi.lua_
Normal file
@@ -0,0 +1,18 @@
|
||||
-- Petit script pour configurer les secrets utilisés pour le wifi
|
||||
-- et que l'on n'aimerait pas être exportés sur Internet (github)
|
||||
-- Il faut donc modifier le .gitignore avec eus_params* et secret*
|
||||
-- il faut le renommer en 'secrets_wifi.lua' et sera exécuté
|
||||
-- par 'wifi_init.lua' une fois pour la configuration du WIFI
|
||||
|
||||
function secrets_wifi()
|
||||
print("\n secrets_wifi.lua zf191222.2002 \n")
|
||||
f= "eus_params.lua" if file.exists(f) then p = dofile(f) end
|
||||
if p ~= nil then
|
||||
cli_ssid = p.wifi_ssid cli_pwd = p.wifi_password p=nil
|
||||
else
|
||||
cli_ssid = "" cli_pwd = ""
|
||||
end
|
||||
ap_ssid="NodeMCU" ap_pwd="ppp"
|
||||
end
|
||||
|
||||
secrets_wifi()
|
||||
308
Mesures/humidity/solar-grafana/_zremote_cmd.txt
Normal file
@@ -0,0 +1,308 @@
|
||||
# Quelques commandes remote (luatool) à envoyer avec le plugin Atom-IDE-terminal de l'éditeur Atom
|
||||
# zf200229.2315
|
||||
|
||||
|
||||
Todo à faire pour ce projet !
|
||||
|
||||
- refaire le fichier _secrets_project.lua_ à partir de secrets_project.lua
|
||||
- faire la documentation pour le fonctionnement de concept de rtelnet dans un fichier à part .md
|
||||
|
||||
- y regarder pour faire tourner en MEME temps le reverse et le forward telnet
|
||||
- z lancement ou arrêt du WEBIDE via la home page
|
||||
v- ajouter fonction restart dans z_index.html (ATTENTION avec un argument restart, pas besoin de faire une page restart.html !)
|
||||
v- ajouter l'adresse du zdyndns dans les secrets projets
|
||||
v- ajouter l'affichage du node_id dans z_index.html
|
||||
v- ajouter le web_srv2 dans boot au lieu de boot2
|
||||
v- ajouter un état du RELAY et de la LED dans z_index.html
|
||||
v- ajouter une page affichage variables globales
|
||||
v- améliorer api_sonoff.html, il faut ajouter 'home' sur la page
|
||||
v- améliorer le résultat de api_sonoff.html, il faut sortir l'état des IO lors d'un changement comme confirmation
|
||||
v- arrêter de demander de connecter le WIFI automatiquement en mode station juste après le boot dans la config wifiinit (automatic connect)
|
||||
v- clignoter la led à chaque mesure en fonction de verbose
|
||||
v- copier secrets_project et secrets_wifi dans _secrets_project_ _secrets_wifi_ pour la documentation
|
||||
v- déplacer le mode AP dans wifi_init
|
||||
v- enlever la ligne wifi init dans z_index.html
|
||||
v- faire la page web service pour allumer la LED
|
||||
v- faire la page web service pour allumer le relay
|
||||
v- faire que send_data et read_temp soient lancés à la volée afin d'économiser de la RAM quand ce n'est pas utilisé
|
||||
v- garder variable node_id pour identification après poweron général, reattribution adrs ip sur modem 4G
|
||||
v- if verbose print partout dans *.lua
|
||||
v- le wifi setup ne fonctionne toujours pas quand il y a déjà un ap de connecté (problème du reboot quand adrs ip ok)!
|
||||
v- mettre le numéro jaune du nodemcu dans les secrets projet et prendre 23000+num_jaune comme numéro de port pour le reverse telnet
|
||||
v- passer à 10 secondes la seconde chance
|
||||
v- passer à 15x les tentatives de connexions au WIFI
|
||||
v- regarder pour mettre "Welcome to NodeMCU world." quand connected, en fait quand on arrive dans le telnet_listener après la redirection du port série !
|
||||
v- se connecter sur le zdyndns avec le numéro du port du telnet reverse utilisé
|
||||
v- terminer la page .html affichage de la température et de l'humidité
|
||||
v- terminer le reverse telnet ;-)
|
||||
v- trouver un moyen pour configurer la lED dans initz.lua sans le rendre dangereux en cas de problème (éviter le reflashing en cas de reboot loop)
|
||||
v- utiliser le bouton pour piloter le verbose
|
||||
v- vérifier le fonctionnement d'allumer la LED, car ne marche plus !
|
||||
x- ajouter argument ok dans wifi_init.html (sécurité)
|
||||
x- mettre ZLED2 et ZRELAY dans secrets_project
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# si luatool ne marche pas sur le MAC, il faut lire ceci:
|
||||
# https://docs.google.com/document/d/1q64uK3IMOgEDdKaIAttbYuFt4GuLQ06k3FLeyfCsWLg/edit#heading=h.bmefcu67uwj0
|
||||
|
||||
# raccourcis clavier
|
||||
# CTRL+ALT+ENTER envoie au terminal la ligne de l'éditeur
|
||||
# SHIT+CTRL+` ouvre le terminal (attention, ne pas oublier de copier le *path* dans le *tree* et le changer)
|
||||
# ALT+CMD+F bascule entre le terminal et l'éditeur
|
||||
|
||||
# définitions à faire AVANT !
|
||||
export luatool_tty="/dev/cu.wchusbserial1410"
|
||||
|
||||
export zIP="192.168.0.182"
|
||||
export zport="23"
|
||||
|
||||
export zIP="localhost"
|
||||
export zport="23000"
|
||||
ATTENTION: voir les tunnels tout à la fin !
|
||||
|
||||
|
||||
# ouvrir et fermer (ALT+N+.) une session telnet sur le NodeMCU avec l'adresse zIP)
|
||||
telnet -rN $zIP $zport
|
||||
~.
|
||||
--node.restart()
|
||||
collectgarbage()
|
||||
=node.heap()
|
||||
for k,v in pairs(_G) do print(k,v) end
|
||||
|
||||
|
||||
################################
|
||||
# commandes lua pour ce projet #
|
||||
################################
|
||||
ssh ubuntu@www.zuzutest.ml killall -9 socat
|
||||
killall -9 ssh
|
||||
ssh ubuntu@www.zuzutest.ml socat TCP-LISTEN:23047,reuseaddr,fork TCP-LISTEN:23000,reuseaddr,bind=127.0.0.1 &
|
||||
watch -n 1 'ssh ubuntu@www.zuzutest.ml netstat -nat |grep 230'
|
||||
ssh -N -L 23000:localhost:23000 ubuntu@www.zuzutest.ml &
|
||||
|
||||
export zIP="localhost"
|
||||
export zport="23000"
|
||||
telnet -rN $zIP $zport
|
||||
for k,v in pairs(_G) do print(k,v) end
|
||||
~.
|
||||
zdyn
|
||||
|
||||
./luatool.py --ip $zIP:$zport -f boot.lua
|
||||
./luatool.py --ip $zIP:$zport -f z_index.html
|
||||
|
||||
./luatool.py --ip $zIP:$zport -f 0_send_data.lua
|
||||
./luatool.py --ip $zIP:$zport -f 0_cron.lua
|
||||
./luatool.py --ip $zIP:$zport -f 0_htu21d.lua
|
||||
|
||||
./luatool.py --ip $zIP:$zport -f api_sonoff.html
|
||||
http://192.168.0.182
|
||||
|
||||
./luatool.py --ip $zIP:$zport -f dir.lua
|
||||
|
||||
telnet -rN $zIP $zport
|
||||
verbose=false
|
||||
~.
|
||||
|
||||
=node.heap()
|
||||
collectgarbage()
|
||||
=node.heap()
|
||||
|
||||
|
||||
dofile("dir.lua")
|
||||
dir()
|
||||
for k,v in pairs(_G) do print(k,v) end
|
||||
dofile("wifi_info.lua")
|
||||
|
||||
node.restart()
|
||||
|
||||
~.
|
||||
./luatool.py --ip $zIP:$zport -f head.lua
|
||||
telnet -rN $zIP $zport
|
||||
dofile("head.lua")
|
||||
zhead("boot.lua")
|
||||
|
||||
|
||||
|
||||
verbose=true
|
||||
verbose=false
|
||||
zsort_rssi() zshow()
|
||||
|
||||
|
||||
#commandes luatool pour ce projet le .137 est à jour avec la nouvelle version du wifi !
|
||||
~.
|
||||
./luatool.py --ip $zIP:$zport -l
|
||||
./luatool.py --ip $zIP:$zport -f wifi_init.lua
|
||||
|
||||
|
||||
./luatool.py --ip $zIP:$zport -f secrets_wifi.lua
|
||||
./luatool.py --ip $zIP:$zport -f initz.lua -t init.lua
|
||||
./luatool.py --ip $zIP:$zport -f boot.lua
|
||||
./luatool.py --ip $zIP:$zport -f boot2.lua
|
||||
./luatool.py --ip $zIP:$zport -f wifi_init.lua
|
||||
./luatool.py --ip $zIP:$zport -f set_time.lua
|
||||
./luatool.py --ip $zIP:$zport -f wifi_info.lua
|
||||
./luatool.py --ip $zIP:$zport -f c.lua
|
||||
./luatool.py --ip $zIP:$zport -f cat.lua
|
||||
./luatool.py --ip $zIP:$zport -f flash_led_xfois.lua
|
||||
./luatool.py --ip $zIP:$zport -f head.lua
|
||||
|
||||
./luatool.py --ip $zIP:$zport -f b.lua
|
||||
./luatool.py --ip $zIP:$zport -f web_srv2.lua
|
||||
./luatool.py --ip $zIP:$zport -f z_index.html
|
||||
|
||||
|
||||
./luatool.py --ip $zIP:$zport -f wifi_get_conf.html
|
||||
./luatool.py --ip $zIP:$zport -f wifi_set_conf.html
|
||||
|
||||
|
||||
./luatool.py --ip $zIP:$zport -f z_page1.html
|
||||
./luatool.py --ip $zIP:$zport -f z_page2.html
|
||||
./luatool.py --ip $zIP:$zport -f z_page3.html
|
||||
./luatool.py --ip $zIP:$zport -f z_page4.html
|
||||
|
||||
./luatool.py --ip $zIP:$zport --delete wifi_ap_start.lua
|
||||
./luatool.py --ip $zIP:$zport --delete wifi_cli_conf.lua
|
||||
./luatool.py --ip $zIP:$zport --delete wifi_cli_start.lua
|
||||
./luatool.py --ip $zIP:$zport --delete dir.lua
|
||||
./luatool.py --ip $zIP:$zport --delete initz.lua
|
||||
./luatool.py --ip $zIP:$zport --delete wifi_conf.lua
|
||||
|
||||
|
||||
|
||||
dofile("wifi_info.lua")
|
||||
--node.restart()
|
||||
for k,v in pairs(_G) do print(k,v) end
|
||||
t=12
|
||||
t=nil
|
||||
print(pcall(function () print("2"..t) end))
|
||||
|
||||
|
||||
|
||||
# ici c'est maintenant ;-)
|
||||
~.
|
||||
./luatool.py --ip $zIP:$zport -f b.lua
|
||||
#./luatool.py --ip $zIP:$zport --zrestart
|
||||
telnet -rN $zIP $zport
|
||||
zsort_rssi() zshow()
|
||||
print(ztrig_rssi)
|
||||
ztrig_rssi=-1000
|
||||
ztrig_rssi=-90
|
||||
|
||||
|
||||
|
||||
# test de la gestion des erreurs
|
||||
~.
|
||||
./luatool.py --ip $zIP:$zport -f c.lua
|
||||
#./luatool.py --ip $zIP:$zport --zrestart
|
||||
telnet -rN $zIP $zport
|
||||
status, err = pcall(function () dofile("c.lua") end) if status==false then print("Error: ",err) end
|
||||
zerr=nil
|
||||
zerr=1
|
||||
ztmr_tst_err:unregister()
|
||||
|
||||
|
||||
|
||||
|
||||
ztmr_tst_err:unregister()
|
||||
for k,v in pairs(_G) do print(k,v) end
|
||||
|
||||
./luatool.py --ip $zIP --zrestart
|
||||
|
||||
|
||||
# faire un cat d'un fichier sur le NodeMCU
|
||||
dofile("cat.lua")
|
||||
cat("boot2.lua")
|
||||
|
||||
|
||||
# commandes luatool
|
||||
./luatool.py -h
|
||||
./luatool.py --ip $zIP:$zport -i
|
||||
./luatool.py --ip $zIP:$zport -l
|
||||
./luatool.py --ip $zIP:$zport -f toto.lua -d
|
||||
./luatool.py --ip $zIP:$zport --delete toto.lua
|
||||
|
||||
|
||||
|
||||
****************************************************************************
|
||||
|
||||
|
||||
# création des tunnels ssh
|
||||
ATTENTION: dans un premier terminal !
|
||||
Pour Bolo à Ruchonnet:
|
||||
ssh -t -L 2323:localhost:2323 ubuntu@www.zuzutest.ml ssh -N -L 2323:192.168.8.102:23 ubuntu@localhost -p 20223
|
||||
|
||||
Pour le Crêt
|
||||
ssh -N -L 2323:192.168.0.137:23 admin@z.zufferey.com -p 1822
|
||||
ssh -N -L 2323:192.168.0.122:23 admin@z.zufferey.com -p 1822
|
||||
ssh -N -L 2323:192.168.0.118:23 admin@z.zufferey.com -p 1822
|
||||
|
||||
ATTENTION: dans un deuxième terminal !
|
||||
export zIP="localhost"
|
||||
export zport="2323"
|
||||
telnet -rN $zIP $zport
|
||||
~.
|
||||
=node.heap()
|
||||
|
||||
verbose=false
|
||||
verbose=true
|
||||
|
||||
dofile("dir2.lua")
|
||||
dir()
|
||||
filec("head.lua")
|
||||
|
||||
dofile("head.lua")
|
||||
zhead("dir2.lua")
|
||||
|
||||
dofile("cat.lua")
|
||||
cat("head.lua")
|
||||
|
||||
~.
|
||||
--node.restart()
|
||||
=node.heap()
|
||||
|
||||
|
||||
status, err = pcall(function () fonction_a_tester() end) if status==false then print("Error: ",err) end
|
||||
status, err = pcall(function () toto() end) if status==false then print("Error: ",err) end
|
||||
|
||||
|
||||
|
||||
Gestion de la passerelle SSH reverse
|
||||
Puis depuis une autre console on peut faire directement pour aller sur l'OpiZ (ici le 20223):
|
||||
ssh -t ubuntu@www.zuzutest.ml ssh ubuntu@localhost -p 20223
|
||||
|
||||
ou
|
||||
|
||||
1ère console
|
||||
On établit le tunnel local avec l'OpiZ
|
||||
ssh -N -L 20223:localhost:20223 ubuntu@www.zuzutest.ml
|
||||
|
||||
|
||||
2ème console, on utilise le tunnel OpiZ en local sur sa machine
|
||||
pour aller sur l'OpiZ
|
||||
ssh ubuntu@localhost -p 20223
|
||||
|
||||
pour copier sa clef SSH depuis un MAC
|
||||
./ssh-copy-id -i ~/.ssh/id_rsa.pub 'ubuntu@localhost -p 20223'
|
||||
après on devrait pouvoir se connecter sans devoir entrer son password à chaque fois
|
||||
ssh ubuntu@localhost -p 20223
|
||||
|
||||
ou, on établit un tunnel pour telnet sur un NodeMCU
|
||||
ssh -L 2323:192.168.0.137:23 ubuntu@localhost -p 20223
|
||||
puis
|
||||
telnet -rN localhost 2323
|
||||
|
||||
ou, on établit un tunnel pour le rpimonotor sur l'OpiZ
|
||||
ssh -N -L 8888:192.168.0.113:8888 ubuntu@localhost -p 20223
|
||||
puis
|
||||
http://localhost:8888
|
||||
|
||||
ou, on établit un tunnel proxy Socket 5 pour le modem 4G HUAWEI sur l'OpiZ
|
||||
ssh -N -D 8080 ubuntu@localhost -p 20223
|
||||
puis depuis le browser FireFox avec le plugin FoxyProxy Socket 5 sur localhost port 8080
|
||||
http://192.168.8.1
|
||||
|
||||
|
||||
|
||||
.
|
||||
39
Mesures/humidity/solar-grafana/api_sonoff.html
Normal file
@@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<!-- ATTENTION, la longueur des lignes DOIT être <128 ! -->
|
||||
|
||||
<html lang="fr" dir="ltr">
|
||||
<head>
|
||||
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
|
||||
<title>API SonOff</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>API SonOff zf200118.1812</h1>
|
||||
<a href="/">Home...</a><br><br>
|
||||
<%
|
||||
if _GET.LED == "on" then
|
||||
gpio.write(zLED, gpio.LOW) gpio.mode(zLED, gpio.OUTPUT)
|
||||
zout("LED=".._GET.LED.."<br>")
|
||||
zout('<a href="api_sonoff.html?LED=off"> Off</a><br>')
|
||||
|
||||
end
|
||||
if _GET.LED == "off" then
|
||||
gpio.write(zLED, gpio.HIGH) gpio.mode(zLED, gpio.OUTPUT)
|
||||
zout("LED=".._GET.LED.."<br>")
|
||||
zout('<a href="api_sonoff.html?LED=on"> On</a>')
|
||||
end
|
||||
%>
|
||||
<%
|
||||
if _GET.RELAY == "on" then
|
||||
gpio.mode(zRELAY, gpio.OUTPUT) gpio.write(zRELAY, gpio.HIGH)
|
||||
zout("RELAY=".._GET.RELAY.."<br>")
|
||||
zout('<a href="api_sonoff.html?RELAY=off"> Off</a><br>')
|
||||
end
|
||||
if _GET.RELAY == "off" then
|
||||
gpio.mode(zRELAY, gpio.OUTPUT) gpio.write(zRELAY, gpio.LOW)
|
||||
zout("RELAY=".._GET.RELAY.."<br>")
|
||||
zout('<a href="api_sonoff.html?RELAY=on"> On</a>')
|
||||
end
|
||||
%>
|
||||
</body>
|
||||
</html>
|
||||
25
Mesures/humidity/solar-grafana/boot.lua
Normal file
@@ -0,0 +1,25 @@
|
||||
-- Scripts à charger après le boot pour démarrer son projet
|
||||
|
||||
print("\n boot.lua zf200303.1409 \n")
|
||||
|
||||
function boot()
|
||||
verbose = true
|
||||
print("On lance le boot...")
|
||||
print(node.heap()) collectgarbage() print(node.heap())
|
||||
|
||||
--f="0_htu21d.lua" if file.exists(f) then dofile(f) end
|
||||
--zurl=thingspeak_url.."field1="..tostring(ztemp1).."&field2="..tostring(zhum1)
|
||||
--f="0_send_data.lua" if file.exists(f) then dofile(f) end
|
||||
f="0_btn_flipflop.lua" if file.exists(f) then dofile(f) end
|
||||
|
||||
f = "0_zdyndns.lua" if file.exists(f) then dofile(f) end
|
||||
f="0_cron.lua" if file.exists(f) then dofile(f) end
|
||||
f="0_tst3_socat.lua" if file.exists(f) then dofile(f) end
|
||||
|
||||
--f = "web_ide2.lua" if file.exists(f) then dofile(f) end
|
||||
print("verbose:",verbose)
|
||||
print("boot lancé...")
|
||||
print(node.heap()) collectgarbage() print(node.heap())
|
||||
f=nil boot=nil
|
||||
end
|
||||
boot()
|
||||
1838
Mesures/humidity/solar-grafana/box/support_capteur_HTU21D.191218.1730.2.dxf
Executable file
|
After Width: | Height: | Size: 19 KiB |
BIN
Mesures/humidity/solar-grafana/box/support_capteur_HTU21D.191218.1730.2.rld
Executable file
@@ -0,0 +1,140 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="297mm"
|
||||
height="210mm"
|
||||
viewBox="0 0 297 210"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="support_capteur_HTU21D.191218.1730.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.9957143"
|
||||
inkscape:cx="320.74445"
|
||||
inkscape:cy="396.85039"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="724"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="1"
|
||||
inkscape:window-maximized="0"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-bbox-midpoints="true">
|
||||
<sodipodi:guide
|
||||
position="40,113.21969"
|
||||
orientation="1,0"
|
||||
id="guide1265"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,0,255)" />
|
||||
<sodipodi:guide
|
||||
position="45.000001,117.72727"
|
||||
orientation="1,0"
|
||||
id="guide1267"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,0,255)" />
|
||||
<sodipodi:guide
|
||||
position="140,158.82576"
|
||||
orientation="1,0"
|
||||
id="guide1269"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,0,255)" />
|
||||
<sodipodi:guide
|
||||
position="135,122.32737"
|
||||
orientation="1,0"
|
||||
id="guide1271"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,0,255)" />
|
||||
<sodipodi:guide
|
||||
position="50.000001,125.30636"
|
||||
orientation="0,1"
|
||||
id="guide4164" />
|
||||
<sodipodi:guide
|
||||
position="50.000001,105.30637"
|
||||
orientation="0,1"
|
||||
id="guide4166" />
|
||||
<sodipodi:guide
|
||||
position="130,120.30636"
|
||||
orientation="0,1"
|
||||
id="guide4168" />
|
||||
<sodipodi:guide
|
||||
position="130,110.30637"
|
||||
orientation="0,1"
|
||||
id="guide4170" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-87)">
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.53638637;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 40.268193,164.46183 99.463617,0 0,34.46361 -99.463617,0 z"
|
||||
id="rect1088"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g4156"
|
||||
transform="translate(-4.9999997,1.75001)">
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.29067463;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 51.604663,169.94363 A 1.6046627,1.6046627 0 0 1 50,171.54829 1.6046627,1.6046627 0 0 1 48.395337,169.94363 1.6046627,1.6046627 0 0 1 50,168.33897 a 1.6046627,1.6046627 0 0 1 1.604663,1.60466 z"
|
||||
id="path1128"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.29067463;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 51.604663,189.94362 A 1.6046627,1.6046627 0 0 1 50,191.54828 1.6046627,1.6046627 0 0 1 48.395337,189.94362 1.6046627,1.6046627 0 0 1 50,188.33896 a 1.6046627,1.6046627 0 0 1 1.604663,1.60466 z"
|
||||
id="circle1130"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g4160"
|
||||
transform="translate(4.999998,1.75001)">
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.29067463;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 131.60466,174.94363 A 1.6046627,1.6046627 0 0 1 130,176.54829 1.6046627,1.6046627 0 0 1 128.39534,174.94363 1.6046627,1.6046627 0 0 1 130,173.33897 a 1.6046627,1.6046627 0 0 1 1.60466,1.60466 z"
|
||||
id="circle1132"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.29067463;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 131.60466,184.94362 A 1.6046627,1.6046627 0 0 1 130,186.54828 1.6046627,1.6046627 0 0 1 128.39534,184.94362 1.6046627,1.6046627 0 0 1 130,183.33896 a 1.6046627,1.6046627 0 0 1 1.60466,1.60466 z"
|
||||
id="circle1134"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
31
Mesures/humidity/solar-grafana/dir.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
-- fonction dir() pour juste afficher les fichiers avec leur taille
|
||||
|
||||
print("\n dir2.lua zf191223.1455 \n")
|
||||
|
||||
function dir()
|
||||
local zdir={}
|
||||
local pfile = file.list()
|
||||
for k,v in pairs(pfile) do
|
||||
zdir[#zdir+1] = k..string.rep(" ",24-string.len(k)).." : "..v
|
||||
end
|
||||
table.sort(zdir) for i=1, #zdir do print(zdir[i]) end
|
||||
size_file=nil chksum_file=nil k=nil
|
||||
end
|
||||
|
||||
dir()
|
||||
print("\nusage:")
|
||||
print(" dir()")
|
||||
|
||||
--[[
|
||||
dir()
|
||||
dirc()
|
||||
filec("dir2.lua")
|
||||
|
||||
=node.heap()
|
||||
clear_dir()
|
||||
=node.heap()
|
||||
|
||||
for k,v in pairs(_G) do print(k,v) end
|
||||
|
||||
status, err = pcall(function () print(zhash("il était une fois trois petits cochons roses...")) end) if status==false then print("Error: ",err) end
|
||||
]]
|
||||
23
Mesures/humidity/solar-grafana/disp_temp.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
|
||||
<title>Affichage de la température et humidité</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Affichage de la température et humidité 200118.1800</h1>
|
||||
<a href="/">Home...</a><br>
|
||||
<%
|
||||
zout("<h1>"..node_id.." 200112.1919 </h1>")
|
||||
%>
|
||||
<br>
|
||||
<%
|
||||
zout("Température: "..readTemp().." °C<br>")
|
||||
zout("Humidité: "..readHumi().." %<br>")
|
||||
|
||||
zout("<br><br>RAM: "..node.heap().."<br>")
|
||||
%>
|
||||
</body>
|
||||
</html>
|
||||
10
Mesures/humidity/solar-grafana/docu/HTU21D.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
-- module https://learn.sparkfun.com/tutorials/htu21d-humidity-sensor-hookup-guide/all
|
||||
-- achat https://www.aliexpress.com/item/32480177429.html
|
||||
-- schéma https://github.com/sparkfun/HTU21D_Breakout/blob/master/hardware/SparkFun_HTU21D_Breakout.pdf
|
||||
-- data sheet https://cdn.sparkfun.com/assets/6/a/8/e/f/525778d4757b7f50398b4567.pdf
|
||||
-- Comparaison DHT22, AM2302, AM2320, AM2321, SHT71, HTU21D, Si7021, BME280
|
||||
-- http://www.kandrsmith.org/RJS/Misc/Hygrometers/calib_many.html
|
||||
-- théorie http://electromag1.wifeo.com/capteurs-de-temperature-et-humidite-gy-21-et-si7021.php
|
||||
-- source lua: https://github.com/tebben/NodeMCU
|
||||
|
||||
-- ATTENTION: il n'y a seulement que certaines combinaisons de pins qui fonctionnent avec le capteur HTU21D avec le NodeMCU !
|
||||
49
Mesures/humidity/solar-grafana/goodies/a.lua
Normal file
@@ -0,0 +1,49 @@
|
||||
print("a start... zf190105.2344")
|
||||
|
||||
|
||||
srv:close()
|
||||
srv=nil
|
||||
|
||||
wifi.setmode(wifi.NULLMODE,true)
|
||||
|
||||
print("toto")
|
||||
tmr.delay(1*1000*1000)
|
||||
print("tutu")
|
||||
|
||||
wifi.setmode(wifi.STATIONAP,true)
|
||||
|
||||
wifi.sta.config{ssid="", pwd="", auto=true, save=true}
|
||||
wifi.sta.autoconnect(1) wifi.sta.connect()
|
||||
wifi.ap.config({ ssid = "toto", auth=wifi.OPEN, save=true })
|
||||
|
||||
wifi.setmode(wifi.STATION,true)
|
||||
|
||||
--wifi.setmode(wifi.STATIONAP)
|
||||
--wifi.ap.config({ssid="MyPersonalSSID", auth=wifi.OPEN})
|
||||
--enduser_setup.manual(true)
|
||||
|
||||
--[[
|
||||
srv:close()
|
||||
srv=nil
|
||||
|
||||
wifi.setmode(wifi.NULLMODE,true)
|
||||
|
||||
print("toto")
|
||||
a1=tmr.create()
|
||||
a1:alarm(10*1000, tmr.ALARM_SINGLE, function()
|
||||
enduser_setup.start(
|
||||
function()
|
||||
print("Connected to WiFi as:" .. wifi.sta.getip())
|
||||
end,
|
||||
function(err, str)
|
||||
print("enduser_setup: Err #" .. err .. ": " .. str)
|
||||
end,
|
||||
print -- Lua print function can serve as the debug callback
|
||||
)
|
||||
print(node.heap()) collectgarbage() print(node.heap())
|
||||
print("tutu")
|
||||
end)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
37
Mesures/humidity/solar-grafana/goodies/c.lua
Normal file
@@ -0,0 +1,37 @@
|
||||
-- Scripts pour tester l'affichage des erreurs quand on se trouve ne remote telnet
|
||||
-- source: https://www.lua.org/pil/8.4.html
|
||||
-- source: https://riptutorial.com/lua/example/16000/using-pcall
|
||||
|
||||
--[[
|
||||
Usage:
|
||||
après l'avoir lancé on peut faire varier le contenu de la variable zerr pour cérer des erreurs répétitives
|
||||
|
||||
Commandes à envoyer via un terminal:
|
||||
~.
|
||||
./luatool.py --ip $zIP:$zport -f c.lua
|
||||
#./luatool.py --ip $zIP:$zport --zrestart
|
||||
telnet -rN $zIP $zport
|
||||
status, err = pcall(function () dofile("c.lua") end) if status==false then print("Error: ",err) end
|
||||
zerr=nil
|
||||
zerr=1
|
||||
ztmr_tst_err:unregister()
|
||||
]]
|
||||
|
||||
print("\n c.lua zf191030.1231 \n")
|
||||
|
||||
zerr=1
|
||||
ztmr_tst_err = tmr.create()
|
||||
|
||||
-- le code à tester DOIT être encapsulé dans une fonction
|
||||
function zfoo()
|
||||
print("toto: "..zerr)
|
||||
end
|
||||
|
||||
-- timer pour générer des erreurs répétitives
|
||||
ztmr_tst_err:alarm(3*1000, tmr.ALARM_AUTO, function()
|
||||
-- test du code
|
||||
local status, err = pcall(function () zfoo() end) if status==false then print("Error: ",err) end
|
||||
end)
|
||||
|
||||
|
||||
--
|
||||
22
Mesures/humidity/solar-grafana/goodies/cat.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
-- fonction cat() pour afficher le contenu d'un fichier dans la flash
|
||||
print("\n cat.lua zf191124.2204 \n")
|
||||
|
||||
function zread_line()
|
||||
local zline = ""
|
||||
while true do
|
||||
local t = zf:read(1) if t == nil then return end
|
||||
zline = zline..t
|
||||
if t == "\n" then return string.sub(zline,1,string.len(zline)-1) end
|
||||
end
|
||||
end
|
||||
|
||||
function cat(zfile)
|
||||
print("\n"..zfile.."\n-------------------------------")
|
||||
zf = file.open(zfile, "r")
|
||||
while true do
|
||||
zline = zread_line() if zline == nil then break end
|
||||
print(zline)
|
||||
end
|
||||
zf:close()
|
||||
print("-------------------------------")
|
||||
end
|
||||
19
Mesures/humidity/solar-grafana/goodies/check_all.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
# Petit script pour contrôler en remote les versions d'une grappe de NodeMCU installés
|
||||
#zf191226.1241
|
||||
|
||||
# crée les tunnels SSH
|
||||
source ./make_tunnels.sh go
|
||||
|
||||
# On liste les fichiers de chaque nodemcu
|
||||
echo -e "th1"
|
||||
./luatool.py --ip localhost:$TH1_PORT --list
|
||||
|
||||
echo -e "th2"
|
||||
./luatool.py --ip localhost:$TH2_PORT --list
|
||||
|
||||
echo -e "th3"
|
||||
./luatool.py --ip localhost:$TH3_PORT --list
|
||||
|
||||
echo -e "th4"
|
||||
./luatool.py --ip localhost:$TH4_PORT --list
|
||||
90
Mesures/humidity/solar-grafana/goodies/dir2.lua
Normal file
@@ -0,0 +1,90 @@
|
||||
-- fonction dirc() pour calculer le checksum de tous les fichiers sur le NodeMCU !
|
||||
-- fonction filec(fichier) pour calculer le checksum d'un seul fichiers sur le NodeMCU !
|
||||
|
||||
print("\n dir2.lua zf191124.1602 \n")
|
||||
|
||||
function calc_chksum_file()
|
||||
local name_file = list_files[zcmpt1]
|
||||
print(name_file)
|
||||
local size_file = 1 local chksum_file = 0
|
||||
local f = file.open(name_file, "r")
|
||||
while true do
|
||||
local t = f:read(1) if t == nil then break end
|
||||
chksum_file = chksum_file + size_file * string.byte(t)
|
||||
size_file = size_file + 1
|
||||
if size_file%100 == 0 then uart.write(0,".") end
|
||||
end
|
||||
f:close() print("")
|
||||
zdir[#zdir+1]=name_file..string.rep(" ",24-string.len(name_file)).." : "..size_file..", "..chksum_file
|
||||
zcmpt1 = zcmpt1 + 1
|
||||
zrepeat()
|
||||
end
|
||||
|
||||
function zrepeat()
|
||||
if zcmpt1 <= #list_files then
|
||||
-- if zcmpt1 <= 3 then
|
||||
node.task.post(calc_chksum_file)
|
||||
else
|
||||
table.sort(zdir) for i=1, #zdir do print(zdir[i]) end
|
||||
zdir=nil list_files=nil zcmpt1=nil
|
||||
end
|
||||
end
|
||||
|
||||
function dirc()
|
||||
zdir={} list_files={}
|
||||
local pfile = file.list()
|
||||
for k,v in pairs(pfile) do
|
||||
list_files[#list_files+1]=k
|
||||
end
|
||||
zcmpt1 = 1 zrepeat()
|
||||
end
|
||||
|
||||
function filec(name_file)
|
||||
print(name_file)
|
||||
local size_file = 1 local chksum_file = 0
|
||||
local f = file.open(name_file, "r")
|
||||
while true do
|
||||
local t = f:read(1) if t == nil then break end
|
||||
chksum_file = chksum_file + size_file * string.byte(t)
|
||||
size_file = size_file + 1
|
||||
if size_file%100 == 0 then uart.write(0,".") end
|
||||
end
|
||||
f:close() print("")
|
||||
print(name_file..string.rep(" ",24-string.len(name_file)).." : "..size_file..", "..chksum_file)
|
||||
end
|
||||
|
||||
function dir()
|
||||
local zdir={}
|
||||
local pfile = file.list()
|
||||
for k,v in pairs(pfile) do
|
||||
zdir[#zdir+1] = k..string.rep(" ",24-string.len(k)).." : "..v
|
||||
end
|
||||
table.sort(zdir) for i=1, #zdir do print(zdir[i]) end
|
||||
size_file=nil chksum_file=nil k=nil
|
||||
end
|
||||
|
||||
function clear_dir()
|
||||
dir=nil dir2=nil dirc=nil filec=nil
|
||||
zrepeat=nil calc_chksum_file=nil
|
||||
end
|
||||
|
||||
dir()
|
||||
print("\nusage:")
|
||||
print(" dir()")
|
||||
print(" dirc()")
|
||||
print(" filec('dir2.lua')")
|
||||
|
||||
|
||||
--[[
|
||||
dir()
|
||||
dirc()
|
||||
filec("dir2.lua")
|
||||
|
||||
=node.heap()
|
||||
clear_dir()
|
||||
=node.heap()
|
||||
|
||||
for k,v in pairs(_G) do print(k,v) end
|
||||
|
||||
status, err = pcall(function () print(zhash("il était une fois trois petits cochons roses...")) end) if status==false then print("Error: ",err) end
|
||||
]]
|
||||
17
Mesures/humidity/solar-grafana/goodies/i2c_scanner.lua
Normal file
@@ -0,0 +1,17 @@
|
||||
-- Scanner for I2C devices
|
||||
-- http://www.esp8266.com/viewtopic.php?f=19&t=771
|
||||
|
||||
print("\n i2c_scanner.lua zf191216.2117 \n")
|
||||
|
||||
id=0 sda=5 scl=6
|
||||
|
||||
print("start...")
|
||||
i2c.setup(id,sda,scl,i2c.SLOW)
|
||||
|
||||
for i=0,127 do
|
||||
i2c.start(id)
|
||||
resCode = i2c.address(id, i, i2c.TRANSMITTER)
|
||||
i2c.stop(id)
|
||||
if resCode == true then print("We have a device on address 0x" .. string.format("%02x", i) .. " (" .. i ..")") end
|
||||
end
|
||||
print("stop...")
|
||||
55
Mesures/humidity/solar-grafana/goodies/make_tunnels.sh
Normal file
@@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
# Petit script pour créer tous les tunnels SSH sur les NodeMCU en remote
|
||||
# zf191226.1239
|
||||
|
||||
#test si l'argument est vide
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo -e "
|
||||
Usage:
|
||||
|
||||
source ./make_tunnels.sh go
|
||||
|
||||
"
|
||||
read -p "continue ?"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Définition des variables
|
||||
export TREMPLIN_SSH=www.zuzutest.ml
|
||||
export OPIZ_PORT=20223
|
||||
|
||||
export TH1_IP=192.168.8.100
|
||||
export TH1_PORT=23001
|
||||
export TH2_IP=192.168.8.101
|
||||
export TH2_PORT=23002
|
||||
export TH3_IP=192.168.8.102
|
||||
export TH3_PORT=23003
|
||||
export TH4_IP=192.168.8.103
|
||||
export TH4_PORT=23004
|
||||
|
||||
|
||||
# On tue tous les tunnels ssh
|
||||
echo "kill"
|
||||
killall -9 ssh
|
||||
sleep 3
|
||||
|
||||
# On crée le tunnel sur la passerelle ssh 20223
|
||||
echo "first"
|
||||
ssh -y -y -N -T -L $OPIZ_PORT:localhost:$OPIZ_PORT ubuntu@$TREMPLIN_SSH &
|
||||
sleep 3
|
||||
|
||||
# On crée tous les tunnels sur les nodemcu
|
||||
echo "second"
|
||||
ssh -y -y -N -T -L $TH1_PORT:$TH1_IP:23 ubuntu@localhost -p $OPIZ_PORT &
|
||||
ssh -y -y -N -T -L $TH2_PORT:$TH2_IP:23 ubuntu@localhost -p $OPIZ_PORT &
|
||||
ssh -y -y -N -T -L $TH3_PORT:$TH3_IP:23 ubuntu@localhost -p $OPIZ_PORT &
|
||||
ssh -y -y -N -T -L $TH4_PORT:$TH4_IP:23 ubuntu@localhost -p $OPIZ_PORT &
|
||||
sleep 3
|
||||
|
||||
echo "end"
|
||||
ps ax |grep ssh
|
||||
36
Mesures/humidity/solar-grafana/goodies/set_time.lua
Normal file
@@ -0,0 +1,36 @@
|
||||
-- Scripts pour régler l'horloge quand on est connecté en WIFI
|
||||
-- Permet aussi de 'compresser' le unix time afin de prendre moins de place dans les strings
|
||||
|
||||
print("\n set_time.lua zf191030.2026 \n")
|
||||
|
||||
--source: https://www.freeformatter.com/epoch-timestamp-to-date-converter.html
|
||||
|
||||
ztime2019 = 1546300800 -- Unix time pour le 1.1.2019
|
||||
|
||||
function set_time()
|
||||
sntp.sync(nil, nil, nil, 1)
|
||||
end
|
||||
|
||||
function ztime_compress(ztime_long)
|
||||
return ztime_long - ztime2019
|
||||
end
|
||||
|
||||
function ztime_uncompress(ztime_short)
|
||||
return ztime_short + ztime2019
|
||||
end
|
||||
|
||||
function ztime_format(ztime)
|
||||
local tm = rtctime.epoch2cal(ztime + 3600)
|
||||
return(string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"]))
|
||||
end
|
||||
|
||||
set_time()
|
||||
|
||||
tmr.create():alarm(2*1000, tmr.ALARM_SINGLE, function()
|
||||
print(ztime_format(rtctime.get()))
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
30
Mesures/humidity/solar-grafana/goodies/up_load_all.sh
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
# Petit script pour télécharger du code en remote sur une grappe de NodeMCU
|
||||
#zf191225.1802
|
||||
|
||||
# crée les tunnels SSH
|
||||
source ./make_tunnels.sh
|
||||
|
||||
export ZFILE="0_cron.lua"
|
||||
export ZRESTART=""
|
||||
#export ZRESTART="--restart"
|
||||
|
||||
# On télécharge le fichier sur chaque nodemcu
|
||||
echo -e "th1"
|
||||
#./luatool.py --ip localhost:$TH1_PORT $ZRESTART -f $ZFILE
|
||||
./luatool.py --ip localhost:$TH1_PORT --zrestart
|
||||
|
||||
echo -e "th2"
|
||||
#./luatool.py --ip localhost:$TH2_PORT $ZRESTART -f $ZFILE
|
||||
./luatool.py --ip localhost:$TH2_PORT --zrestart
|
||||
|
||||
echo -e "th3"
|
||||
#./luatool.py --ip localhost:$TH3_PORT $ZRESTART -f $ZFILE
|
||||
./luatool.py --ip localhost:$TH3_PORT --zrestart
|
||||
|
||||
echo -e "th4"
|
||||
#./luatool.py --ip localhost:$TH4_PORT $ZRESTART -f $ZFILE
|
||||
./luatool.py --ip localhost:$TH4_PORT --zrestart
|
||||
|
||||
|
||||
#
|
||||
38
Mesures/humidity/solar-grafana/goodies/upload_t.sh
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
# Petit script pour télécharger facilement tout le binz
|
||||
#zf191028.1459
|
||||
|
||||
# S'il y a des erreurs lors d'un téléchargement, il faut simplement augmenter un peu le délai !
|
||||
# Il est préférable de télécharger en premier les *gros* fichiers .lua !
|
||||
|
||||
# ATTENTION: cela efface tout le NodeMCU !
|
||||
|
||||
luatool_tty="/dev/cu.wchusbserial1410"
|
||||
|
||||
echo ""
|
||||
read -p "ATTENTION, cela va effacer tout le NodeMCU !"
|
||||
read -p "Etes-vous vraiment certain ?"
|
||||
|
||||
chmod +x luatool.py
|
||||
|
||||
./luatool.py --port $luatool_tty -w
|
||||
./luatool.py --port $luatool_tty -l
|
||||
read -p "Est-ce bien vide ?"
|
||||
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.06 -f telnet_srv2.lua
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.03 -f head.lua
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.03 -f flash_led_xfois.lua
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.001 -f wifi_info.lua
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.001 -f wifi_cli_start.lua
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.001 -f wifi_cli_conf.lua
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.001 -f wifi_ap_stop.lua
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.001 -f secrets_energy.lua
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.001 -f dir.lua
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.001 -f cat.lua
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.001 -f boot2.lua
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.001 -f boot.lua
|
||||
|
||||
./luatool.py --port $luatool_tty -l
|
||||
read -p "Pas eu d'erreur, on part à fond avec le init.lua ?"
|
||||
./luatool.py --port $luatool_tty --bar --delay 0.001 -f initz.lua -t init.lua
|
||||
echo -e "\nC'est tout bon ;-)"
|
||||
63
Mesures/humidity/solar-grafana/goodies/wifi_clear.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
|
||||
<title>Wifi clear</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Wifi clear 191222.2348</h1>
|
||||
<br>
|
||||
Effacement de la configuration WIFI actuelle !<br>
|
||||
<a href="/">Retour à la home page...</a><br><br><br>
|
||||
|
||||
Test d'un web service qui fonctionne avec l'Active Server Page ZYX.<br><br>
|
||||
|
||||
Le code Lua pour afficher ce résultat se trouve dans le code HTML de cette page et est exécuté sur
|
||||
le NodeMCU.<br>
|
||||
Les données viennent du NodeMCU !<br><br>
|
||||
|
||||
<%
|
||||
zout("Il reste: "..node.heap().." de RAM !<br><br>\n")
|
||||
%>
|
||||
|
||||
<%
|
||||
zout("Booooooooum dans 5 secondes!<br>")
|
||||
tmr.create():alarm(5*1000, tmr.ALARM_SINGLE, function()
|
||||
file.remove("eus_params.lua")
|
||||
node.restart()
|
||||
end)
|
||||
|
||||
%>
|
||||
|
||||
Les arguments du web service (GET) sont:<br><br>
|
||||
<%
|
||||
if (vars ~= nil) then
|
||||
zout("<br>vars: "..vars.."<br>")
|
||||
for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
|
||||
_GET[k] = v
|
||||
zout(k..": "..v.."<br>")
|
||||
if k == "field1" then
|
||||
ztemp1_conc = v
|
||||
elseif k == "field2" then
|
||||
ztemp2_conc = v
|
||||
elseif k == "field3" then
|
||||
ztemp3_conc = v
|
||||
end
|
||||
end
|
||||
end
|
||||
zout("<br>Les températures récupérées sont: "..ztemp1_conc..", "..ztemp2_conc..", "..ztemp3_conc)
|
||||
%>
|
||||
|
||||
|
||||
|
||||
|
||||
<br><br>Yeah... cela fonctionne vachement bien !<br><br>
|
||||
|
||||
<%
|
||||
zout("Il reste: "..node.heap().." de RAM !<br><br>\n")
|
||||
%>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
48
Mesures/humidity/solar-grafana/goodies/wifi_set_conf.html
Normal file
@@ -0,0 +1,48 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
|
||||
<title>WIFI set config</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>WIFI set config 191124.2334</h1>
|
||||
<br>
|
||||
Coucou c'est WIFI set config !<br>
|
||||
<a href="/">Retour à la home page...</a><br><br><br>
|
||||
|
||||
|
||||
|
||||
<%
|
||||
|
||||
if (vars ~= nil) then
|
||||
zout("<br>vars: "..vars.."<br><br>")
|
||||
for k, v in string.gmatch(vars, "(%w+)=(%w+%p+%w+)&*") do
|
||||
_GET[k] = v
|
||||
zout(k..": "..v.."<br>")
|
||||
end
|
||||
end
|
||||
|
||||
zout("<br>toto<br>")
|
||||
|
||||
--[[
|
||||
zout("t1: ",_GET.zssid,"<br>")
|
||||
zout("t2: ",_GET.zpasswd,"<br>")
|
||||
|
||||
if zverif == "YES" then
|
||||
zout("c'est tout bon")
|
||||
zout("Le SSID est: ",zssid)
|
||||
zout("Le PASSWD est: ",zpasswd)
|
||||
end
|
||||
]]
|
||||
|
||||
ztemp=ztemp+1
|
||||
zout(ztemp.."°C")
|
||||
%>
|
||||
|
||||
<br>Mais il fait encore trop froid !<br>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
67
Mesures/humidity/solar-grafana/goodies/zz_host_dir.lua
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/local/bin/lua5.1
|
||||
-- script lua à faire tourner sur le host pour la taille de tous les fichiers
|
||||
-- du dossier en cours, donc PAS sur le NodeMCU !
|
||||
-- source: https://stackoverflow.com/questions/5303174/how-to-get-list-of-directories-in-lua (30%)
|
||||
|
||||
-- usage dans la console:
|
||||
-- ./zz_host_dir.lua
|
||||
--[[
|
||||
./zz_host_dir.lua > thost
|
||||
]]
|
||||
-- usage dans Atom editor
|
||||
-- il faut installer ceci: https://atom.io/packages/compare-files
|
||||
-- puis sélectionner les deux fichiers dans l'explorateur à gauche puis CTRL+CMD+C
|
||||
|
||||
|
||||
print("\n zz_host_dir.lua zf191124.1646 \n")
|
||||
|
||||
function calc_chksum_file(name_file)
|
||||
size_file = 0 chksum_file = 0
|
||||
local f = io.open(name_file, "r")
|
||||
-- local f = file.open(name_file, "r")
|
||||
while true do
|
||||
local t = f:read(1) if t == nil then break end
|
||||
-- chksum_file = chksum_file + size_file * string.byte(t)
|
||||
size_file = size_file + 1
|
||||
-- if size_file%100 == 0 then uart.write(0,".") end
|
||||
end
|
||||
f:close()
|
||||
-- print(name_file)
|
||||
end
|
||||
|
||||
function dirfile(k)
|
||||
calc_chksum_file(k)
|
||||
print(k..string.rep(" ",24-string.len(k)).." : "..size_file..", "..chksum_file)
|
||||
size_file=nil chksum_file=nil k=nil
|
||||
end
|
||||
|
||||
function dir()
|
||||
local zdir={}
|
||||
local pfile = io.popen("ls -1r *.lua *.html")
|
||||
for k in pfile:lines() do
|
||||
-- local pfile = file.list()
|
||||
-- for k,v in pairs(pfile) do
|
||||
calc_chksum_file(k)
|
||||
if (size_file ~= 1) and (chksum_file ~= 1) then
|
||||
zdir[#zdir+1]=k..string.rep(" ",24-string.len(k)).." : "..size_file
|
||||
end
|
||||
end
|
||||
pfile:close()
|
||||
table.sort(zdir)
|
||||
for i=1, #zdir do
|
||||
print(zdir[i])
|
||||
end
|
||||
size_file=nil chksum_file=nil k=nil
|
||||
end
|
||||
|
||||
dir()
|
||||
print("\n\nRappel, sur Atom, sélectionner les deux fichiers à gauche puis CTRL+CMD+C\n")
|
||||
|
||||
--[[
|
||||
dir()
|
||||
dirfile("dir2.lua")
|
||||
|
||||
for k,v in pairs(_G) do print(k,v) end
|
||||
|
||||
status, err = pcall(function () print(zhash("il était une fois trois petits cochons roses...")) end) if status==false then print("Error: ",err) end
|
||||
]]
|
||||
67
Mesures/humidity/solar-grafana/goodies/zz_host_dir2.lua
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/local/bin/lua5.1
|
||||
-- script lua à faire tourner sur le host pour calculer le checksum de tous les fichiers
|
||||
-- du dossier en cours, donc PAS sur le NodeMCU !
|
||||
-- source: https://stackoverflow.com/questions/5303174/how-to-get-list-of-directories-in-lua (30%)
|
||||
|
||||
-- usage dans la console:
|
||||
-- ./zz_host_dir2.lua
|
||||
--[[
|
||||
./zz_host_dir2.lua > thost
|
||||
]]
|
||||
-- usage dans Atom editor
|
||||
-- il faut installer ceci: https://atom.io/packages/compare-files
|
||||
-- puis sélectionner les deux fichiers dans l'explorateur à gauche puis CTRL+CMD+C
|
||||
|
||||
|
||||
print("\n zz_host_dir2.lua zf191124.1634 \n")
|
||||
|
||||
function calc_chksum_file(name_file)
|
||||
size_file = 1 chksum_file = 0
|
||||
local f = io.open(name_file, "r")
|
||||
-- local f = file.open(name_file, "r")
|
||||
while true do
|
||||
local t = f:read(1) if t == nil then break end
|
||||
chksum_file = chksum_file + size_file * string.byte(t)
|
||||
size_file = size_file + 1
|
||||
-- if size_file%100 == 0 then uart.write(0,".") end
|
||||
end
|
||||
f:close()
|
||||
-- print(name_file)
|
||||
end
|
||||
|
||||
function dirfile(k)
|
||||
calc_chksum_file(k)
|
||||
print(k..string.rep(" ",24-string.len(k)).." : "..size_file..", "..chksum_file)
|
||||
size_file=nil chksum_file=nil k=nil
|
||||
end
|
||||
|
||||
function dir()
|
||||
local zdir={}
|
||||
local pfile = io.popen("ls -1r ")
|
||||
for k in pfile:lines() do
|
||||
-- local pfile = file.list()
|
||||
-- for k,v in pairs(pfile) do
|
||||
calc_chksum_file(k)
|
||||
if (size_file ~= 1) and (chksum_file ~= 1) then
|
||||
zdir[#zdir+1]=k..string.rep(" ",24-string.len(k)).." : "..size_file..", "..chksum_file
|
||||
end
|
||||
end
|
||||
pfile:close()
|
||||
table.sort(zdir)
|
||||
for i=1, #zdir do
|
||||
print(zdir[i])
|
||||
end
|
||||
size_file=nil chksum_file=nil k=nil
|
||||
end
|
||||
|
||||
dir()
|
||||
print("\n\nRappel, sur Atom, sélectionner les deux fichiers à gauche puis CTRL+CMD+C\n")
|
||||
|
||||
--[[
|
||||
dir()
|
||||
dirfile("dir2.lua")
|
||||
|
||||
for k,v in pairs(_G) do print(k,v) end
|
||||
|
||||
status, err = pcall(function () print(zhash("il était une fois trois petits cochons roses...")) end) if status==false then print("Error: ",err) end
|
||||
]]
|
||||
19
Mesures/humidity/solar-grafana/head.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
-- fonction cat() pour afficher les 10 premières lignes d'un fichier dans la flash
|
||||
print("\n head.lua zf192028.1516 \n")
|
||||
|
||||
function zhead(zfile)
|
||||
print("\n"..zfile.."\n-------------------------------")
|
||||
|
||||
zfilei = file.open(zfile, "r")
|
||||
i=1
|
||||
zline=file.readline()
|
||||
repeat
|
||||
-- print(i..": "..string.sub(zline,1,string.len(zline)-1))
|
||||
print(string.sub(zline,1,string.len(zline)-1))
|
||||
i=i+1 zline=file.readline()
|
||||
if i>10 then break end
|
||||
until zline==nil
|
||||
file.close(zfilei)
|
||||
|
||||
print("-------------------------------")
|
||||
end
|
||||
|
After Width: | Height: | Size: 966 KiB |
BIN
Mesures/humidity/solar-grafana/img/HTU21D.jpg
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
Mesures/humidity/solar-grafana/img/HTU21D_deporte.jpg
Normal file
|
After Width: | Height: | Size: 793 KiB |
BIN
Mesures/humidity/solar-grafana/img/banc_test_HTU21D.jpg
Normal file
|
After Width: | Height: | Size: 662 KiB |
BIN
Mesures/humidity/solar-grafana/img/graph_thingspeak1.png
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
Mesures/humidity/solar-grafana/img/htu21d_on_NodeMCU.jpg
Normal file
|
After Width: | Height: | Size: 713 KiB |
|
After Width: | Height: | Size: 969 KiB |
|
After Width: | Height: | Size: 329 KiB |
79
Mesures/humidity/solar-grafana/initz.lua
Normal file
@@ -0,0 +1,79 @@
|
||||
--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 zf200118.1507 \n")
|
||||
|
||||
function initz()
|
||||
|
||||
function initz_end()
|
||||
print("initz_end...")
|
||||
f= "wifi_init.lua" if file.exists(f) then dofile(f) end
|
||||
f=nil initz=nil second_chance=nil hvbouton=nil initz_end=nil
|
||||
print(node.heap()) collectgarbage() print(node.heap())
|
||||
print("initz_end out...")
|
||||
end
|
||||
|
||||
function hvbouton()
|
||||
gpio.trig(zswitch, "none") zswitch=nil
|
||||
print("hvbouton...")
|
||||
initalarme1:unregister() initalarme1=nil second_chance=nil
|
||||
gpio.write(zLED, gpio.HIGH) zLED=nil
|
||||
reset_reason="hvbouton"
|
||||
initz_end()
|
||||
end
|
||||
|
||||
function second_chance()
|
||||
print("seconde chance...")
|
||||
zLED=4 -- NodeMCU
|
||||
--zLED=7 -- SonOff
|
||||
gpio.write(zLED, gpio.LOW) gpio.mode(zLED, gpio.OUTPUT)
|
||||
initalarme1=tmr.create()
|
||||
initalarme1:alarm(10*1000, tmr.ALARM_SINGLE, function()
|
||||
gpio.write(zLED, gpio.HIGH) zLED=nil
|
||||
gpio.trig(zswitch, "none") zswitch=nil
|
||||
reset_reason="seconde_chance"
|
||||
initz_end()
|
||||
end)
|
||||
zswitch=3 --switch flash ou SonOff
|
||||
gpio.mode(zswitch, gpio.INT, gpio.PULLUP)
|
||||
gpio.trig(zswitch, "both", hvbouton)
|
||||
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")
|
||||
initz_end()
|
||||
elseif reset_reason == 5 then
|
||||
print("dsleep wake up")
|
||||
initz_end()
|
||||
elseif reset_reason == 6 then
|
||||
print("external reset")
|
||||
second_chance()
|
||||
else
|
||||
print("autre raison")
|
||||
second_chance()
|
||||
end
|
||||
end
|
||||
initz()
|
||||
|
||||
--[[
|
||||
zLED=7
|
||||
gpio.mode(zLED, gpio.OUTPUT)
|
||||
gpio.write(zLED, gpio.LOW) -- actif !
|
||||
gpio.write(zLED, gpio.HIGH)
|
||||
|
||||
zBTN=3
|
||||
gpio.mode(zBTN, gpio.INPUT)
|
||||
print(gpio.read(zBTN))
|
||||
|
||||
zRELAY=6
|
||||
gpio.mode(zRELAY, gpio.OUTPUT)
|
||||
gpio.write(zRELAY, gpio.HIGH) -- actif !
|
||||
gpio.write(zRELAY, gpio.LOW)
|
||||
]]
|
||||
408
Mesures/humidity/solar-grafana/luatool.py
Executable file
@@ -0,0 +1,408 @@
|
||||
#!/usr/bin/env python2
|
||||
# -*- coding: utf-8 -*-
|
||||
version = "0.6.8 zf191225.1428"
|
||||
|
||||
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):
|
||||
##zzz191124 enlève la fin de ligne afin de ne pas perturber la vérification finale
|
||||
data = data.rstrip('\r\n')
|
||||
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 != '':
|
||||
#zzz191124 line = line.strip()
|
||||
# zzz191021 Affiche ce que l'on a reçu du NodeMCU
|
||||
if args.verbose:
|
||||
print("\n\nzread0957: {" + line + "\n}\n")
|
||||
|
||||
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
|
||||
|
||||
# zzz191021 juste après l'ouverture du port série, on attend le caractère '>'
|
||||
line = ''
|
||||
char = ''
|
||||
i = -1
|
||||
while char != chr(62): # '>'
|
||||
char = self.read(1)
|
||||
if char == '':
|
||||
raise Exception('No proper answer from MCU')
|
||||
line += char
|
||||
i += 1
|
||||
if args.verbose:
|
||||
print("line: ." + line + ".")
|
||||
|
||||
|
||||
def writeln(self, data, check=1):
|
||||
# zzz191020 on fait une petite pause avant 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])
|
||||
##zzz191124 attend encore un petit peu avant d'envoyer
|
||||
sleep(self.delay)
|
||||
self.serial.write(data)
|
||||
sleep(self.delay)
|
||||
# zzz191021 Affiche ce que l'on a envoyé au NodeMCU
|
||||
if args.verbose:
|
||||
print("\n\nzwrite0952: {" + data + "\n}\n")
|
||||
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('--bar', action='store_true', help='Show a progress bar for uploads instead of printing each line')
|
||||
parser.add_argument('--delay', default=0.025, 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 via telnet server (--ip IP[:port])')
|
||||
parser.add_argument('--zrestart', action='store_true', help='Restart the NodeMCU.')
|
||||
parser.add_argument('-a', '--append', action='store_true', help='Append source file to destination file.')
|
||||
parser.add_argument('-b', '--baud', default=115200, help='Baudrate, default 115200')
|
||||
parser.add_argument('-c', '--compile', action='store_true', help='Compile lua to lc after upload')
|
||||
parser.add_argument('-d', '--dofile', action='store_true', help='Run the Lua script after upload')
|
||||
parser.add_argument('-e', '--echo', action='store_true', help='Echo output of MCU until script is terminated.')
|
||||
parser.add_argument('-f', '--src', default='main.lua', help='Source file on computer, default main.lua')
|
||||
parser.add_argument('-i', '--id', action='store_true', help='Query the modules chip id.')
|
||||
parser.add_argument('-l', '--list', action='store_true', help='List files on device')
|
||||
parser.add_argument('-p', '--port', default='/dev/ttyUSB0', help='Device name, default /dev/ttyUSB0')
|
||||
parser.add_argument('-r', '--restart', action='store_true', help='Restart MCU after upload')
|
||||
parser.add_argument('-t', '--dest', default=None, help='Destination file on MCU, default to source file name')
|
||||
parser.add_argument('-v', '--verbose', action='store_true', help="Show progress messages.")
|
||||
parser.add_argument('-w', '--wipe', action='store_true', help='Delete all lua/lc files on device.')
|
||||
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)
|
||||
# zzz191225 Amélioré encore la sortie du listing des fichiers (sort file)
|
||||
transport.writeln("zdir={};pfile = file.list();for k,v in pairs(pfile) do zdir[#zdir+1] = k..string.rep(' ',24-string.len(k))..' : '..v end;table.sort(zdir);print('\\n-----');for i=1, #zdir do print(zdir[i]) end;print('-----\\n');zdir=nil;pfile=nil;k=nil;v=nil;i=nil\r", 0)
|
||||
|
||||
while True:
|
||||
char = transport.read(1)
|
||||
if char == '' or char == chr(62): # '' or '>'
|
||||
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)
|
||||
|
||||
# zzz191020 Ajouté la fonction restart seule
|
||||
if args.zrestart:
|
||||
transport.writeln("node.restart()\r")
|
||||
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)
|
||||
# zzz191020 Affiche le fichier à envoyer
|
||||
print("File: " + 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)):
|
||||
#zzz191124 transport.writer(line.strip())
|
||||
transport.writer(line)
|
||||
line = f.readline()
|
||||
else:
|
||||
while line != '':
|
||||
#zzz191124 transport.writer(line.strip())
|
||||
transport.writer(line)
|
||||
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")
|
||||
BIN
Mesures/humidity/solar-grafana/schema/pcb.png
Normal file
|
After Width: | Height: | Size: 161 KiB |
BIN
Mesures/humidity/solar-grafana/schema/schema.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
93
Mesures/humidity/solar-grafana/telnet_srv2.lua
Normal file
@@ -0,0 +1,93 @@
|
||||
-- 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 zf191020.1932 \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
|
||||
|
||||
--zzz
|
||||
local function zconnection(s)
|
||||
print("Welcome to NodeMCU world.")
|
||||
end
|
||||
|
||||
socket:on("connection", zconnection)
|
||||
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")
|
||||
48
Mesures/humidity/solar-grafana/upload_s.sh
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/bin/bash
|
||||
# Petit script pour télécharger facilement tout le binz via le port série
|
||||
#zf191228.2313
|
||||
|
||||
# S'il y a des erreurs lors d'un téléchargement, il faut simplement augmenter un peu le délai !
|
||||
# Il est préférable de télécharger en premier les *gros* fichiers .lua !
|
||||
|
||||
# ATTENTION: cela efface tout le NodeMCU !
|
||||
|
||||
luatool_tty="/dev/cu.wchusbserial1410"
|
||||
|
||||
echo ""
|
||||
read -p "ATTENTION, cela va effacer tout le NodeMCU !"
|
||||
read -p "Etes-vous vraiment certain ?"
|
||||
|
||||
chmod +x luatool.py
|
||||
|
||||
./luatool.py --port $luatool_tty -w
|
||||
./luatool.py --port $luatool_tty -l
|
||||
read -p "Est-ce bien vide ?"
|
||||
|
||||
./luatool.py --port $luatool_tty --bar -f z_index.html
|
||||
./luatool.py --port $luatool_tty --bar -f wifi_init.lua
|
||||
./luatool.py --port $luatool_tty --bar -f wifi_info.lua
|
||||
./luatool.py --port $luatool_tty --bar -f wifi_clear.html
|
||||
./luatool.py --port $luatool_tty --bar -f web_srv2.lua
|
||||
./luatool.py --port $luatool_tty --bar -f web_ide2.lua
|
||||
./luatool.py --port $luatool_tty --bar -f telnet_srv2.lua
|
||||
./luatool.py --port $luatool_tty --bar -f set_time.lua
|
||||
./luatool.py --port $luatool_tty --bar -f secrets_wifi.lua
|
||||
./luatool.py --port $luatool_tty --bar -f secrets_project.lua
|
||||
./luatool.py --port $luatool_tty --bar -f head.lua
|
||||
./luatool.py --port $luatool_tty --bar -f eus_params.lua
|
||||
./luatool.py --port $luatool_tty --bar -f disp_temp.html
|
||||
./luatool.py --port $luatool_tty --bar -f dir2.lua
|
||||
./luatool.py --port $luatool_tty --bar -f cat.lua
|
||||
./luatool.py --port $luatool_tty --bar -f boot2.lua
|
||||
./luatool.py --port $luatool_tty --bar -f boot.lua
|
||||
./luatool.py --port $luatool_tty --bar -f 0_send_data.lua
|
||||
#./luatool.py --port $luatool_tty --bar -f 0_htu21d.lua
|
||||
./luatool.py --port $luatool_tty --bar -f 0_cron.lua
|
||||
|
||||
./luatool.py --port $luatool_tty -l
|
||||
read -p "Pas eu d'erreur, on part à fond avec le init.lua ?"
|
||||
|
||||
./luatool.py --port $luatool_tty --bar -f initz.lua -t init.lua
|
||||
./luatool.py --port $luatool_tty -l
|
||||
echo -e "\nC'est tout bon ;-)"
|
||||
159
Mesures/humidity/solar-grafana/web_ide2.lua
Normal file
@@ -0,0 +1,159 @@
|
||||
-- Petit WEB IDE tout simple autonome
|
||||
-- ATTENTION: tourne sur le port 88 !
|
||||
|
||||
print("\n _web_ide2.lua zf181221.1137 \n")
|
||||
|
||||
--[[
|
||||
XChip's NodeMCU IDE
|
||||
|
||||
Create, Edit and run NodeMCU files using your webbrowser.
|
||||
Examples:
|
||||
http://<mcu_ip>/ will list all the files in the MCU
|
||||
http://<mcu_ip>/newfile.lua displays the file on your browser
|
||||
http://<mcu_ip>/newfile.lua?edit allows to creates or edits the specified script in your browser
|
||||
http://<mcu_ip>/newfile.lua?run it will run the specified script and will show the returned value
|
||||
]]--
|
||||
|
||||
srv=net.createServer(net.TCP)
|
||||
srv:listen(88,function(conn)
|
||||
|
||||
local rnrn=0
|
||||
local Status = 0
|
||||
local DataToGet = 0
|
||||
local method=""
|
||||
local url=""
|
||||
local vars=""
|
||||
|
||||
conn:on("receive",function(conn,payload)
|
||||
|
||||
if Status==0 then
|
||||
_, _, method, url, vars = string.find(payload, "([A-Z]+) /([^?]*)%??(.*) HTTP")
|
||||
print(method, url, vars)
|
||||
end
|
||||
|
||||
if method=="POST" then
|
||||
|
||||
if Status==0 then
|
||||
--print("status", Status)
|
||||
_,_,DataToGet, payload = string.find(payload, "Content%-Length: (%d+)(.+)")
|
||||
if DataToGet~=nil then
|
||||
DataToGet = tonumber(DataToGet)
|
||||
--print(DataToGet)
|
||||
rnrn=1
|
||||
Status = 1
|
||||
else
|
||||
print("bad length")
|
||||
end
|
||||
end
|
||||
|
||||
-- find /r/n/r/n
|
||||
if Status==1 then
|
||||
--print("status", Status)
|
||||
local payloadlen = string.len(payload)
|
||||
local mark = "\r\n\r\n"
|
||||
local i
|
||||
for i=1, payloadlen do
|
||||
if string.byte(mark, rnrn) == string.byte(payload, i) then
|
||||
rnrn=rnrn+1
|
||||
if rnrn==5 then
|
||||
payload = string.sub(payload, i+1,payloadlen)
|
||||
file.open(url, "w")
|
||||
file.close()
|
||||
Status=2
|
||||
break
|
||||
end
|
||||
else
|
||||
rnrn=1
|
||||
end
|
||||
end
|
||||
if Status==1 then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if Status==2 then
|
||||
--print("status", Status)
|
||||
if payload~=nil then
|
||||
DataToGet=DataToGet-string.len(payload)
|
||||
--print("DataToGet:", DataToGet, "payload len:", string.len(payload))
|
||||
file.open(url, "a+")
|
||||
file.write(payload)
|
||||
file.close()
|
||||
else
|
||||
conn:send("HTTP/1.1 200 OK\r\n\r\nERROR")
|
||||
Status=0
|
||||
end
|
||||
|
||||
if DataToGet==0 then
|
||||
conn:send("HTTP/1.1 200 OK\r\n\r\nOK")
|
||||
Status=0
|
||||
end
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
DataToGet = -1
|
||||
|
||||
if url == "favicon.ico" then
|
||||
conn:send("HTTP/1.1 404 file not found")
|
||||
return
|
||||
end
|
||||
|
||||
conn:send("HTTP/1.1 200 OK\r\n\r\n")
|
||||
|
||||
-- it wants a file in particular
|
||||
if url~="" and vars=="" then
|
||||
DataToGet = 0
|
||||
return
|
||||
end
|
||||
|
||||
conn:send("<html><body><h1>NodeMCU IDE</h1>")
|
||||
|
||||
if vars=="edit" then
|
||||
conn:send("<script>function tag(c){document.getElementsByTagName('w')[0].innerHTML=c};\n")
|
||||
conn:send("var x=new XMLHttpRequest()\nx.onreadystatechange=function(){if(x.readyState==4) document.getElementsByName('t')[0].value = x.responseText; };\nx.open('GET',location.pathname,true)\nx.send()</script>")
|
||||
conn:send("<h2><a href='/'>Back to file list</a>\n")
|
||||
conn:send("<br><br><button onclick=\"tag('Saving');x.open('POST',location.pathname,true);\nx.onreadystatechange=function(){if(x.readyState==4) tag(x.responseText);};\nx.send(new Blob(")
|
||||
conn:send("[document.getElementsByName('t')[0].value],{type:'text/plain'}));\">Save</button><a href='?run'>run</a><w></w>")
|
||||
conn:send("</h2><br><textarea name=t cols=110 rows=50></textarea></br>")
|
||||
end
|
||||
|
||||
if vars=="run" then
|
||||
conn:send("<verbatim>")
|
||||
local st, result=pcall(dofile, url)
|
||||
conn:send(tostring(result))
|
||||
conn:send("</verbatim>")
|
||||
end
|
||||
|
||||
if url=="" then
|
||||
local l = file.list();
|
||||
for k,v in pairs(l) do
|
||||
conn:send("<a href='"..k.."?edit'>"..k.."</a>, size:"..v.."<br>")
|
||||
end
|
||||
end
|
||||
|
||||
conn:send("</body></html>")
|
||||
|
||||
end)
|
||||
conn:on("sent",function(conn)
|
||||
if DataToGet>=0 and method=="GET" then
|
||||
if file.open(url, "r") then
|
||||
file.seek("set", DataToGet)
|
||||
local line=file.read(512)
|
||||
file.close()
|
||||
if line then
|
||||
conn:send(line)
|
||||
DataToGet = DataToGet + 512
|
||||
|
||||
if (string.len(line)==512) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
conn:close()
|
||||
end)
|
||||
end)
|
||||
print("listening, free:", node.heap())
|
||||
67
Mesures/humidity/solar-grafana/web_srv2.lua
Normal file
@@ -0,0 +1,67 @@
|
||||
-- petit script de serveur WEB avec Active Server Page ZYX
|
||||
-- permet d'exécuter du code LUA inline dans l'HTML !
|
||||
|
||||
print("\n web_srv2.lua zf200112.1926 \n")
|
||||
|
||||
-- envoie sur le port ouvert mais depuis l'environnement global !
|
||||
function zout(zstring)
|
||||
if string.len(zstring) > 0 then
|
||||
zzclient:send(zstring) -- envoie le résultat du code lua inline
|
||||
end
|
||||
end
|
||||
|
||||
-- envoie un fichier HTML sur le port. ATTENTION: longueur de la ligne maximale de 1'024 bytes !
|
||||
function send_file(zclient, zfilename)
|
||||
print("start send html...")
|
||||
zclient:send("HTTP/1.1 200 OK\n")
|
||||
zclient:send("Content-Type: text/html\n\n")
|
||||
zzclient = zclient -- export le port sur l'environnement global !
|
||||
if zfilename == "" then zfilename = "z_index.html" end
|
||||
file_web = file.open(zfilename, "r")
|
||||
if file_web then
|
||||
repeat
|
||||
local line = file_web:readline()
|
||||
if line then
|
||||
if string.find(line, "<%%") then
|
||||
flag_lua_code = true -- bascule sur le code lua inline
|
||||
lua_code = ""
|
||||
elseif string.find(line, "%%>") then
|
||||
flag_lua_code = false -- revient sur le code HTML
|
||||
loadstring(lua_code)() --on exécute ici le code lua inline !
|
||||
lua_code = nil
|
||||
elseif flag_lua_code then
|
||||
lua_code = lua_code..line -- récupère le code lua inline
|
||||
else
|
||||
zclient:send(line) -- envoie le code HTML
|
||||
end
|
||||
end
|
||||
until not line
|
||||
file_web:close() file_web = nil flag_lua_code=nil zzclient=nil
|
||||
else
|
||||
zclient:send("<html><h1>"..zfilename.." not found - 404 error</h1><a href='/'>Home</a><br></html>")
|
||||
end
|
||||
end
|
||||
|
||||
srv = net.createServer()
|
||||
srv:listen(80, function(conn)
|
||||
conn:on("receive", function(client, request)
|
||||
_, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP")
|
||||
if not string.find(request, "/favicon.ico") then
|
||||
print("coucou")
|
||||
if (method == nil) then
|
||||
_, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP")
|
||||
end
|
||||
print("method: ", method) print("path: ", path) print("vars: ", vars)
|
||||
_GET = {}
|
||||
if (vars ~= nil) then
|
||||
for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
|
||||
_GET[k] = v
|
||||
print(k..": "..v)
|
||||
end
|
||||
end
|
||||
file_html=string.gsub(path, "/", "")
|
||||
send_file(client, file_html) file_html=nil _GET=nil
|
||||
end
|
||||
end)
|
||||
conn:on("sent", function(c) c:close() end)
|
||||
end)
|
||||
45
Mesures/humidity/solar-grafana/wifi_info.lua
Normal file
@@ -0,0 +1,45 @@
|
||||
-- Petit script pour afficher les infos actuel du WIFI
|
||||
print("\n wifi_info.lua zf200106.1803 \n")
|
||||
|
||||
function wifi_info()
|
||||
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\n")
|
||||
print("AP IP: ", wifi.ap.getip())
|
||||
print("Current AP config:")
|
||||
local ap_config=wifi.ap.getconfig(true)
|
||||
print("\tssid:", ap_config.ssid)
|
||||
print("\tpassword:", ap_config.pwd)
|
||||
print("\tbssid:", wifi.ap.getmac())
|
||||
elseif zmodewifi == wifi.STATIONAP then
|
||||
print("WIFI mode CLI+AP\n")
|
||||
print("CLIENT 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.."\n")
|
||||
print("AP IP: ", wifi.ap.getip())
|
||||
print("Current AP config:")
|
||||
local ap_config=wifi.ap.getconfig(true)
|
||||
print("\tssid:", ap_config.ssid)
|
||||
print("\tpassword:", ap_config.pwd)
|
||||
print("\tbssid:", wifi.ap.getmac())
|
||||
end
|
||||
wifi_info=nil
|
||||
end
|
||||
wifi_info()
|
||||
|
||||
85
Mesures/humidity/solar-grafana/wifi_init.lua
Normal file
@@ -0,0 +1,85 @@
|
||||
-- Petit script pour initaliser la couche WIFI
|
||||
|
||||
function wifi_init()
|
||||
print("\n wifi_init.lua zf200229.2330 \n")
|
||||
|
||||
f= "secrets_wifi.lua" if file.exists(f) then dofile(f) end
|
||||
f= "secrets_project.lua" if file.exists(f) then dofile(f) end
|
||||
|
||||
function wifi_init_end()
|
||||
tmr_wifi_init1:unregister() i=nil
|
||||
f= "wifi_info.lua" if file.exists(f) then dofile(f) end
|
||||
f=nil secrets_wifi=nil cli_pwd=nil cli_ssid=nil
|
||||
tmr_wifi_init1=nil wifi_init=nil
|
||||
print(node.heap()) collectgarbage() print(node.heap())
|
||||
-- f= "telnet_srv2.lua" if file.exists(f) then dofile(f) end
|
||||
f= "web_srv2.lua" if file.exists(f) then dofile(f) end
|
||||
print(node.heap()) collectgarbage() print(node.heap())
|
||||
zdelay=1 if reset_reason=="seconde_chance" then zdelay=20 end
|
||||
tmr_wifi_init3=tmr.create()
|
||||
tmr_wifi_init3:alarm(zdelay*1000, tmr.ALARM_SINGLE, function()
|
||||
f= "boot.lua" if file.exists(f) then dofile(f) end
|
||||
tmr_wifi_init3:unregister() tmr_wifi_init3=nil wifi_init_end=nil
|
||||
reset_reason=nil zdelay=nil
|
||||
end)
|
||||
end
|
||||
|
||||
if file.exists("_setup_wifi_") then
|
||||
print("setup wifi...")
|
||||
file.remove("_setup_wifi_")
|
||||
wifi.sta.config{ssid="", pwd=""} wifi.sta.connect()
|
||||
if zLED == nil then zLED = 4 end
|
||||
gpio.write(zLED, gpio.HIGH) gpio.mode(zLED, gpio.OUTPUT)
|
||||
tmr_wifi_init4=tmr.create()
|
||||
tmr_wifi_init4:alarm(0.1*1000, tmr.ALARM_AUTO , function()
|
||||
gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH)
|
||||
end)
|
||||
tmr.create():alarm(90*1000, tmr.ALARM_SINGLE, function()
|
||||
node.restart()
|
||||
end)
|
||||
enduser_setup.start(function()
|
||||
print("on est sortit du setup wifi et on restart !")
|
||||
node.restart()
|
||||
end)
|
||||
print("setup gadget lancé...")
|
||||
else
|
||||
wifi.setmode(wifi.STATIONAP,true)
|
||||
wifi.sta.config{ssid=cli_ssid, pwd=cli_pwd} wifi.sta.connect()
|
||||
if node_id == nil then node_id = "generic" ap_pwd = "12345678" end
|
||||
wifi.ap.config({ ssid = ap_ssid.."_"..node_id, pwd = ap_pwd, save=true })
|
||||
ap_ssid=nil ap_pwd=nil
|
||||
tmr_wifi_init2=tmr.create()
|
||||
tmr_wifi_init2:alarm(60*1000, tmr.ALARM_SINGLE, function()
|
||||
print("BOOOOUM, y'a plus de AP WIFI !")
|
||||
wifi.setmode(wifi.STATION,true) tmr_wifi_init2=nil
|
||||
print(node.heap()) collectgarbage() print(node.heap())
|
||||
end)
|
||||
gpio.write(zLED, gpio.HIGH) gpio.mode(zLED, gpio.OUTPUT) i=1
|
||||
tmr_wifi_init1=tmr.create()
|
||||
tmr_wifi_init1:alarm(1*1000, tmr.ALARM_AUTO , function()
|
||||
gpio.write(zLED, gpio.LOW) tmr.delay(10000) gpio.write(zLED, gpio.HIGH)
|
||||
if wifi.sta.getip() == nil then
|
||||
print(i,"Connecting to AP...")
|
||||
i=i+1
|
||||
if i > 30 then
|
||||
print("pas de wifi :-(")
|
||||
file.putcontents("_setup_wifi_", "toto")
|
||||
print("on restart pour le setup wifi")
|
||||
node.restart()
|
||||
--tmr_wifi_init2:unregister() tmr_wifi_init2=nil
|
||||
--wifi.setmode(wifi.SOFTAP,true)
|
||||
--wifi_init_end()
|
||||
end
|
||||
else
|
||||
wifi_init_end()
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
wifi_init()
|
||||
|
||||
--[[
|
||||
file.putcontents("_setup_wifi_", "toto")
|
||||
file.remove("eus_params.lua")
|
||||
]]
|
||||
103
Mesures/humidity/solar-grafana/z_index.html
Normal file
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<!-- ATTENTION, la longueur des lignes DOIT être <128 ! -->
|
||||
|
||||
<html lang="fr" dir="ltr">
|
||||
<head>
|
||||
<meta charset='utf-8' name='viewport' content='width=device-width, initial-scale=1.0'>
|
||||
<%
|
||||
zout("<title>"..node_id.."</title>")
|
||||
%>
|
||||
</head>
|
||||
<body>
|
||||
<%
|
||||
zout("<h1>"..node_id.." 200118.1804 </h1>")
|
||||
%>
|
||||
<a href="/">Home...</a><br>
|
||||
<h2>Menu:</h2>
|
||||
<h3>
|
||||
|
||||
LED
|
||||
<a href="api_sonoff.html?LED=on"> On</a>
|
||||
<a href="api_sonoff.html?LED=off"> Off</a><br>
|
||||
|
||||
<a href="disp_temp.html">Affichage de la température et humidité</a><br>
|
||||
<br>
|
||||
<a href="z_index.html?SetupWIFI=true">Wifi setup</a><br>
|
||||
</h3>
|
||||
|
||||
<%
|
||||
if _GET.SetupWIFI == "true" then
|
||||
print("On demande le setup wifi depuis le browser !")
|
||||
wifi_setup_ok=(math.floor(100*node.random()))
|
||||
zout("<br><br>Etes-vous vraiment certain ?<br>Si oui, faites: ")
|
||||
zout('<a href="/?SetupWIFI='..wifi_setup_ok..'"> Ok</a><br><br>')
|
||||
end
|
||||
%>
|
||||
|
||||
<%
|
||||
if (wifi_setup_ok ~= nil) and (_GET.SetupWIFI == tostring(wifi_setup_ok)) then
|
||||
print("On confirme le setup wifi depuis le browser !")
|
||||
zout("<br><br>Choisir comme WIFI AP: setup_gadget puis aller sur: http://192.168.4.1<br><br>")
|
||||
file.putcontents("_setup_wifi_", "toto")
|
||||
tmr.create():alarm(5*1000, tmr.ALARM_SINGLE, function()
|
||||
print("on restart pour le setup wifi")
|
||||
wifi.sta.config{ssid="", pwd="", auto=true, save=true}
|
||||
wifi.sta.autoconnect(1) wifi.sta.connect()
|
||||
node.restart()
|
||||
end)
|
||||
end
|
||||
%>
|
||||
|
||||
<%
|
||||
if _GET.RESTART == "true" then
|
||||
print("oups restart...")
|
||||
zout("<br><br>oups restart...<br><br>")
|
||||
tmr.create():alarm(5*1000, tmr.ALARM_SINGLE, function()
|
||||
print("on restart...")
|
||||
node.restart()
|
||||
end)
|
||||
end
|
||||
%>
|
||||
|
||||
<%
|
||||
zout("Etat de la LED:<nsp>")
|
||||
if gpio.read(zLED) == 1 then zout("OFF") else zout("ON") end
|
||||
zout("<br>")
|
||||
%>
|
||||
|
||||
<%
|
||||
if zRELAY ~= nil then
|
||||
zout("Etat du RELAY:<nsp>")
|
||||
if gpio.read(zRELAY) == 0 then zout("OFF") else zout("ON") end
|
||||
zout("<br>")
|
||||
end
|
||||
%>
|
||||
|
||||
<%
|
||||
a,b,c = wifi.sta.getip()
|
||||
if a ~= nil then
|
||||
zout("<br>IP: "..a.."<br>\n".."MASK: "..b.."<br>\n".."GATEWAY: "..c.."<br>\n")
|
||||
a=nil b=nil c=nil
|
||||
end
|
||||
collectgarbage() zout("RAM: "..node.heap().."<br>")
|
||||
%>
|
||||
|
||||
<%
|
||||
zout("<br>Etat des GLOBALS !<br>\n")
|
||||
zout("<table>\n")
|
||||
for k,v in pairs(_G) do
|
||||
if k ~= "lua_code" then
|
||||
v = tostring(v)
|
||||
zout("<tr>")
|
||||
zout("<td>"..k.."</td>") zout("<td>"..v.."</td>")
|
||||
zout("</tr>\n")
|
||||
end
|
||||
end
|
||||
zout("</table>")
|
||||
%>
|
||||
|
||||
<br><br><a href="/?RESTART=true"> Restart !</a><br>
|
||||
|
||||
</body>
|
||||
</html>
|
||||