Add all files to source control even though they are messy and don't do much yet
This commit is contained in:
parent
49d8dc8d43
commit
f52e8f47e6
21
README-old.md
Normal file
21
README-old.md
Normal file
@ -0,0 +1,21 @@
|
||||
# GARAGE
|
||||
|
||||
This project uses an [ESP2866](http://www.esp8266.com) with [nodeMCU](http://nodemcu.com/index_cn.html) firmware to control a garage door.
|
||||
|
||||
Controlling a garage door from a microcontroller is easy. All you need to do is emulate a push button with a relay and wire it in parallel with the real push button on your garage door motor.
|
||||
|
||||
# Hardware
|
||||
|
||||
I bought a [kit from eBay](http://www.ebay.com/itm/281519483801?_trksid=p2059210.m2749.l2649) that came with most of what I needed:
|
||||
* A cheap CH430 USB to Serial TTL adapter with 3.3V logic
|
||||
* A bunch of female to female jumper wires and jumpers
|
||||
* A somewhat useful carrying board that makes access to GPIO pins impossible as soldered.
|
||||
* AM1117 5V to 3.3V power supply with 800 mA capacity.
|
||||
* Female USB cable
|
||||
* ESP-01 board, which gives access to 2 GPIO pins.
|
||||
|
||||
Separately, I bought [2 relays](http://www.ebay.com/itm/2pcs-3V-Relay-High-Level-Driver-Module-optocouple-Relay-Moduele-for-Arduino-/141523155660?) that can handle way more voltage and current than I need, but are handy because I can drive them with 3.3V logic of the ESP2866.
|
||||
|
||||
# Open issues
|
||||
|
||||
* When the ESP2866 powers up, both GPIO pins are in input mode, which the relay reads as logic high. That's not good, as it would trigger a garage door opening! I need to invert the logic. What's the easiest and cheapest way to do this?
|
||||
213
b64.lua
Executable file
213
b64.lua
Executable file
@ -0,0 +1,213 @@
|
||||
#!/usr/local/bin/lua
|
||||
-- http://lua-users.org/wiki/BaseSixtyFour
|
||||
-- working lua base64 codec (c) 2006-2008 by Alex Kloss
|
||||
-- compatible with lua 5.1
|
||||
-- http://www.it-rfc.de
|
||||
-- licensed under the terms of the LGPL2
|
||||
|
||||
-- bitshift functions (<<, >> equivalent)
|
||||
-- shift left
|
||||
function lsh(value,shift)
|
||||
return (value*(2^shift)) % 256
|
||||
end
|
||||
|
||||
-- shift right
|
||||
function rsh(value,shift)
|
||||
return math.floor(value/2^shift) % 256
|
||||
end
|
||||
|
||||
-- return single bit (for OR)
|
||||
function bit(x,b)
|
||||
return (x % 2^b - x % 2^(b-1) > 0)
|
||||
end
|
||||
|
||||
-- logic OR for number values
|
||||
function lor(x,y)
|
||||
result = 0
|
||||
for p=1,8 do result = result + (((bit(x,p) or bit(y,p)) == true) and 2^(p-1) or 0) end
|
||||
return result
|
||||
end
|
||||
|
||||
-- encryption table
|
||||
local base64chars = {
|
||||
[0]='A',
|
||||
[1]='B',
|
||||
[2]='C',
|
||||
[3]='D',
|
||||
[4]='E',
|
||||
[5]='F',
|
||||
[6]='G',
|
||||
[7]='H',
|
||||
[8]='I',
|
||||
[9]='J',
|
||||
[10]='K',
|
||||
[11]='L',
|
||||
[12]='M',
|
||||
[13]='N',
|
||||
[14]='O',
|
||||
[15]='P',
|
||||
[16]='Q',
|
||||
[17]='R',
|
||||
[18]='S',
|
||||
[19]='T',
|
||||
[20]='U',
|
||||
[21]='V',
|
||||
[22]='W',
|
||||
[23]='X',
|
||||
[24]='Y',
|
||||
[25]='Z',
|
||||
[26]='a',
|
||||
[27]='b',
|
||||
[28]='c',
|
||||
[29]='d',
|
||||
[30]='e',
|
||||
[31]='f',
|
||||
[32]='g',
|
||||
[33]='h',
|
||||
[34]='i',
|
||||
[35]='j',
|
||||
[36]='k',
|
||||
[37]='l',
|
||||
[38]='m',
|
||||
[39]='n',
|
||||
[40]='o',
|
||||
[41]='p',
|
||||
[42]='q',
|
||||
[43]='r',
|
||||
[44]='s',
|
||||
[45]='t',
|
||||
[46]='u',
|
||||
[47]='v',
|
||||
[48]='w',
|
||||
[49]='x',
|
||||
[50]='y',
|
||||
[51]='z',
|
||||
[52]='0',
|
||||
[53]='1',
|
||||
[54]='2',
|
||||
[55]='3',
|
||||
[56]='4',
|
||||
[57]='5',
|
||||
[58]='6',
|
||||
[59]='7',
|
||||
[60]='8',
|
||||
[61]='9',
|
||||
[62]='-',
|
||||
[63]='_'
|
||||
}
|
||||
|
||||
-- function encode
|
||||
-- encodes input string to base64.
|
||||
function enc(data)
|
||||
local bytes = {}
|
||||
local result = ""
|
||||
for spos=0,string.len(data)-1,3 do
|
||||
for byte=1,3 do bytes[byte] = string.byte(string.sub(data,(spos+byte))) or 0 end
|
||||
result = string.format('%s%s%s%s%s',result,base64chars[rsh(bytes[1],2)],base64chars[lor(lsh((bytes[1] % 4),4), rsh(bytes[2],4))] or "=",((#data-spos) > 1) and base64chars[lor(lsh(bytes[2] % 16,2), rsh(bytes[3],6))] or "=",((#data-spos) > 2) and base64chars[(bytes[3] % 64)] or "=")
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
-- decryption table
|
||||
local base64bytes = {
|
||||
['A']=0,
|
||||
['B']=1,
|
||||
['C']=2,
|
||||
['D']=3,
|
||||
['E']=4,
|
||||
['F']=5,
|
||||
['G']=6,
|
||||
['H']=7,
|
||||
['I']=8,
|
||||
['J']=9,
|
||||
['K']=10,
|
||||
['L']=11,
|
||||
['M']=12,
|
||||
['N']=13,
|
||||
['O']=14,
|
||||
['P']=15,
|
||||
['Q']=16,
|
||||
['R']=17,
|
||||
['S']=18,
|
||||
['T']=19,
|
||||
['U']=20,
|
||||
['V']=21,
|
||||
['W']=22,
|
||||
['X']=23,
|
||||
['Y']=24,
|
||||
['Z']=25,
|
||||
['a']=26,
|
||||
['b']=27,
|
||||
['c']=28,
|
||||
['d']=29,
|
||||
['e']=30,
|
||||
['f']=31,
|
||||
['g']=32,
|
||||
['h']=33,
|
||||
['i']=34,
|
||||
['j']=35,
|
||||
['k']=36,
|
||||
['l']=37,
|
||||
['m']=38,
|
||||
['n']=39,
|
||||
['o']=40,
|
||||
['p']=41,
|
||||
['q']=42,
|
||||
['r']=43,
|
||||
['s']=44,
|
||||
['t']=45,
|
||||
['u']=46,
|
||||
['v']=47,
|
||||
['w']=48,
|
||||
['x']=49,
|
||||
['y']=50,
|
||||
['z']=51,
|
||||
['0']=52,
|
||||
['1']=53,
|
||||
['2']=54,
|
||||
['3']=55,
|
||||
['4']=56,
|
||||
['5']=57,
|
||||
['6']=58,
|
||||
['7']=59,
|
||||
['8']=60,
|
||||
['9']=61,
|
||||
['-']=62,
|
||||
['_']=63,
|
||||
['=']=nil
|
||||
}
|
||||
|
||||
-- function decode
|
||||
-- decode base64 input to string
|
||||
function dec(data)
|
||||
local chars = {}
|
||||
local result=""
|
||||
for dpos=0,string.len(data)-1,4 do
|
||||
for char=1,4 do chars[char] = base64bytes[(string.sub(data,(dpos+char),(dpos+char)) or "=")] end
|
||||
result = string.format(
|
||||
'%s%s%s%s',
|
||||
result,
|
||||
string.char(lor(lsh(chars[1],2), rsh(chars[2],4))),
|
||||
(chars[3] ~= nil) and string.char(lor(lsh(chars[2],4),
|
||||
rsh(chars[3],2))) or "",
|
||||
(chars[4] ~= nil) and string.char(lor(lsh(chars[3],6) % 192,
|
||||
(chars[4]))) or ""
|
||||
)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
-- command line if not called as library
|
||||
if (arg ~= nil) then
|
||||
local func = 'enc'
|
||||
for n,v in ipairs(arg) do
|
||||
if (n > 0) then
|
||||
if (v == "-h") then print "base64.lua [-e] [-d] text/data" break
|
||||
elseif (v == "-e") then func = 'enc'
|
||||
elseif (v == "-d") then func = 'dec'
|
||||
else print(_G[func](v)) end
|
||||
end
|
||||
end
|
||||
else
|
||||
module('base64',package.seeall)
|
||||
end
|
||||
10
b64.py
Normal file
10
b64.py
Normal file
@ -0,0 +1,10 @@
|
||||
import argparse
|
||||
import base64
|
||||
|
||||
# Load this source file and strip the header.
|
||||
initial_data = 'Marcos'
|
||||
|
||||
encoded_data = base64.b64encode(initial_data)
|
||||
|
||||
num_initial = len(initial_data)
|
||||
print encoded_data
|
||||
23
escape.py
Normal file
23
escape.py
Normal file
@ -0,0 +1,23 @@
|
||||
# esta es una prueba para modificar luatool.py
|
||||
# http://stackoverflow.com/a/18935765/316875
|
||||
from string import maketrans
|
||||
|
||||
def escapeString(a_string):
|
||||
translationTable = maketrans({"-": r"\-", "]": r"\]", "\\": r"\\", "^": r"\^", "$": r"\$", "*": r"\*", ".": r"\."})
|
||||
escaped = a_string.translate(translationTable)
|
||||
return escaped
|
||||
|
||||
print escapeString("Marcos")
|
||||
|
||||
|
||||
#!/usr/bin/python
|
||||
'''
|
||||
|
||||
intab = "aeiou"
|
||||
outtab = "12345"
|
||||
trantab = maketrans(intab, outtab)
|
||||
|
||||
str = "this is string example....wow!!!";
|
||||
print str.translate(trantab);
|
||||
|
||||
'''
|
||||
50
garage.lua
Normal file
50
garage.lua
Normal file
@ -0,0 +1,50 @@
|
||||
print('Welcome to GARAGE')
|
||||
print(' Created by Marcos Kirsch')
|
||||
|
||||
require "webServer"
|
||||
|
||||
pinGarage = 4 -- GPIO2
|
||||
clientTimeoutInSeconds = 10
|
||||
port = 80
|
||||
|
||||
-- Prepare pins
|
||||
function preparePin(pin)
|
||||
-- Pins start out configured for input, and the relay has a pulldown resistor
|
||||
-- in order to prevent from activating on reset. Makes ure to set pin to low
|
||||
-- BEFORE setting to output, less the relay see it as a toggle.
|
||||
gpio.write(pin, gpio.LOW)
|
||||
gpio.mode(pin, gpio.OUTPUT)
|
||||
end
|
||||
preparePin(pinGarage)
|
||||
|
||||
-- This functions emulates pushing the button for opening/closing the garage door.
|
||||
function pushTheButton(pin)
|
||||
gpio.write(pin, gpio.HIGH)
|
||||
delayInMicroseconds = 500000 -- half a second should be enough
|
||||
tmr.delay(delayInMicroseconds)
|
||||
gpio.write(pin, gpio.LOW)
|
||||
end
|
||||
|
||||
-- Read the "garage remote" HTML that is served
|
||||
--file.open("remote.html", "r")
|
||||
--html = file.read()
|
||||
|
||||
webServer.start(port, clientTimeoutInSeconds)
|
||||
|
||||
--
|
||||
--server = net.createServer(net.TCP, clientTimeoutInSeconds) server:listen(port, function(connection)
|
||||
-- --if server == nil
|
||||
-- -- print("Server listening on port " .. port)
|
||||
-- -- return
|
||||
-- --end
|
||||
-- connection:on("receive",function(connection,payload)
|
||||
-- print(payload) -- for debugging only
|
||||
-- --generates HTML web site
|
||||
-- connection:send(httpHeader200 .. html)
|
||||
--
|
||||
-- pushTheButton(pinGarage)
|
||||
-- connection:on("sent",function(connection) connection:close() end)
|
||||
-- end)
|
||||
--end)
|
||||
|
||||
|
||||
79
httpserver.lua
Normal file
79
httpserver.lua
Normal file
@ -0,0 +1,79 @@
|
||||
-- httpserver
|
||||
-- Author: Marcos Kirsch
|
||||
-- This is a very simple HTTP server designed to work on nodemcu (http://nodemcu.com)
|
||||
-- It can handle GET and POST.
|
||||
require "printTable"
|
||||
|
||||
|
||||
httpserver = {}
|
||||
|
||||
|
||||
-- Starts web server in the specified port.
|
||||
--function httpserver.start(port, clientTimeoutInSeconds, debug)
|
||||
-- -- Server constants
|
||||
-- server = net.createServer(net.TCP, clientTimeoutInSeconds) server:listen(port, private.handleRequest)
|
||||
--end
|
||||
|
||||
|
||||
httpserver.private = {} -- not part of the public API
|
||||
|
||||
function httpserver.private.onReceive(connection, payload)
|
||||
print(payload) -- for debugging
|
||||
|
||||
-- parse payload and decide what to serve.
|
||||
parsedRequest = private.parseRequest(payload)
|
||||
httpserver.private.printTable(parsedRequest, 3)
|
||||
|
||||
--generates HTML web site
|
||||
httpHeader200 = "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\n\r\n"
|
||||
html = "<h1>Hola mundo</h1>"
|
||||
connection:send(httpHeader200 .. html)
|
||||
end
|
||||
|
||||
function httpserver.private.handleRequest(connection)
|
||||
connection:on("receive", onReceive)
|
||||
connection:on("sent",function(connection) connection:close() end)
|
||||
end
|
||||
|
||||
-- given an HTTP request, returns the method (i.e. GET)
|
||||
function httpserver.private.getRequestMethod(request)
|
||||
-- HTTP Request Methods.
|
||||
-- HTTP servers are required to implement at least the GET and HEAD methods
|
||||
-- http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods
|
||||
httpMethods = {"GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "OPTIONS", "CONNECT", "PATCH"}
|
||||
method = nil
|
||||
for i=1,#httpMethods do
|
||||
found = string.find(request, httpMethods[i])
|
||||
if found == 1 then
|
||||
break
|
||||
end
|
||||
end
|
||||
return (httpMethods[found])
|
||||
end
|
||||
|
||||
-- given an HTTP request, returns a table with all the information.
|
||||
function httpserver.private.parseRequest(request)
|
||||
parsedRequest = {}
|
||||
-- First get the method
|
||||
|
||||
parsedRequest["method"] = httpserver.private.getRequestMethod(request)
|
||||
if parsedRequest["method"] == nil then
|
||||
return nil
|
||||
end
|
||||
-- Now get each value out of the header, skip the first line
|
||||
lineNumber = 0
|
||||
for line in request:gmatch("[^\r\n]+") do
|
||||
if lineNumber ~=0 then
|
||||
-- tag / value are of the style "Host: 10.0.7.15". Break them up.
|
||||
found, valueIndex = string.find(line, ": ")
|
||||
if found == nil then
|
||||
break
|
||||
end
|
||||
tag = string.sub(line, 1, found - 1)
|
||||
value = string.sub(line, found + 2, #line)
|
||||
parsedRequest[tag] = value
|
||||
end
|
||||
lineNumber = lineNumber + 1
|
||||
end
|
||||
return parsedRequest
|
||||
end
|
||||
23
init.lua
Normal file
23
init.lua
Normal file
@ -0,0 +1,23 @@
|
||||
-- Tell the chip to connect to the access point
|
||||
|
||||
print('Welcome')
|
||||
wifi.setmode(wifi.STATION)
|
||||
print('set mode=STATION (mode='..wifi.getmode()..')')
|
||||
print('MAC: ',wifi.sta.getmac())
|
||||
print('chip: ',node.chipid())
|
||||
print('heap: ',node.heap())
|
||||
wifi.sta.config("Internet","")
|
||||
|
||||
-- Wait until WiFi connection is established
|
||||
|
||||
tmr.alarm(0, 2000, 1, function()
|
||||
if wifi.sta.getip() == nil then
|
||||
print("Connecting to AP...")
|
||||
else
|
||||
print('IP: ',wifi.sta.getip())
|
||||
tmr.stop(0)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
--dofile("garage.lua")
|
||||
30
printTable.lua
Normal file
30
printTable.lua
Normal file
@ -0,0 +1,30 @@
|
||||
-- Print anything - including nested tables
|
||||
-- Based on but modified from:
|
||||
-- http://lua-users.org/wiki/TableSerialization
|
||||
function printTable (tt, indent, done)
|
||||
done = done or {}
|
||||
indent = indent or 0
|
||||
if tt == nil then
|
||||
io.write("nil\n")
|
||||
else
|
||||
if type(tt) == "table" then
|
||||
for key, value in pairs (tt) do
|
||||
io.write(string.rep (" ", indent)) -- indent it
|
||||
if type (value) == "table" and not done [value] then
|
||||
done [value] = true
|
||||
io.write(string.format("[%s] => table\n", tostring (key)));
|
||||
io.write(string.rep (" ", indent+4)) -- indent it
|
||||
io.write("(\n");
|
||||
table_print (value, indent + 7, done)
|
||||
io.write(string.rep (" ", indent+4)) -- indent it
|
||||
io.write(")\n");
|
||||
else
|
||||
io.write(string.format("[%s] => %s\n",
|
||||
tostring (key), tostring(value)))
|
||||
end
|
||||
end
|
||||
else
|
||||
io.write(tt .. "\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
10
remote.html
Normal file
10
remote.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html><head><meta charset="UTF-8"><title>Garage</title></head>
|
||||
<body bgcolor="#999999">
|
||||
<h1>Garage</h1>
|
||||
<form action="" method="POST">
|
||||
<input style="width:40%" name="door" type="submit" value="0">
|
||||
<input style="width:40%;line-height:80%" name="door" type="submit" value="1">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
25
test.lua
Normal file
25
test.lua
Normal file
@ -0,0 +1,25 @@
|
||||
-- figuring out how to parse http header
|
||||
require "webServer"
|
||||
--require "printTable"
|
||||
--require "b64"
|
||||
|
||||
sep = "\r\n"
|
||||
requestForGet =
|
||||
"GET /index.html HTTP/1.1" .. sep ..
|
||||
"Host: 10.0.7.15" .. sep ..
|
||||
"Accept-Encoding: gzip, deflate" .. sep ..
|
||||
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" .. sep ..
|
||||
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/600.3.18 (KHTML, like Gecko) Version/8.0.3 Safari/600.3.18" .. sep ..
|
||||
"Accept-Language: en-us" .. sep ..
|
||||
"Cache-Control: max-age=0" .. sep ..
|
||||
"Connection: keep-alive" .. sep ..
|
||||
""
|
||||
--print(enc(requestForGet))
|
||||
--print(dec(enc(requestForGet)))
|
||||
|
||||
parsedRequest = webServer.private.parseRequest(requestForGet)
|
||||
|
||||
--printTable(parsedRequest, 3)
|
||||
--printTable(nodemcu-http-server, 3)
|
||||
--parsedRequest = webServer.parseRequest(requestForGet)
|
||||
|
||||
59
testfile.txt
Normal file
59
testfile.txt
Normal file
@ -0,0 +1,59 @@
|
||||
testfile
|
||||
|
||||
local foo = bar[i]
|
||||
|
||||
_, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
|
||||
|
||||
00000
|
||||
|
||||
00010
|
||||
0123456789
|
||||
00020
|
||||
01234567890123456789
|
||||
00030
|
||||
012345678901234567890123456789
|
||||
00040
|
||||
0123456789012345678901234567890123456789
|
||||
00050
|
||||
01234567890123456789012345678901234567890123456789
|
||||
00060
|
||||
012345678901234567890123456789012345678901234567890123456789
|
||||
00070
|
||||
0123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00080
|
||||
01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00090
|
||||
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00110
|
||||
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00120
|
||||
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00130
|
||||
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00140
|
||||
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00150
|
||||
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00160
|
||||
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00170
|
||||
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00180
|
||||
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00190
|
||||
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00200
|
||||
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00210
|
||||
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00220
|
||||
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00230
|
||||
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00240
|
||||
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00250
|
||||
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
00260
|
||||
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user