nabaztag_hack_kit 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +4 -0
- data/README.md +119 -0
- data/Rakefile +21 -0
- data/bin/mtl_comp +41 -0
- data/bin/mtl_merge +22 -0
- data/bin/mtl_simu +40 -0
- data/bytecode/lib/buffer.mtl +109 -0
- data/bytecode/lib/button.mtl +27 -0
- data/bytecode/lib/data_helper.mtl +88 -0
- data/bytecode/lib/ear.mtl +90 -0
- data/bytecode/lib/led.mtl +33 -0
- data/bytecode/lib/rfid.mtl +50 -0
- data/bytecode/main.mtl +129 -0
- data/config.ru +6 -0
- data/ext/bytecode/Commands.md +172 -0
- data/ext/bytecode/Docs.md +488 -0
- data/ext/bytecode/README.md +5 -0
- data/ext/bytecode/lib/arp.mtl +159 -0
- data/ext/bytecode/lib/cfg.mtl +74 -0
- data/ext/bytecode/lib/choreos.mtl +1487 -0
- data/ext/bytecode/lib/dhcp.mtl +152 -0
- data/ext/bytecode/lib/dns.mtl +89 -0
- data/ext/bytecode/lib/http.mtl +84 -0
- data/ext/bytecode/lib/tcp.mtl +340 -0
- data/ext/bytecode/lib/udp.mtl +49 -0
- data/ext/bytecode/lib/util.mtl +74 -0
- data/ext/bytecode/lib/var.mtl +15 -0
- data/ext/bytecode/lib/wifi.mtl +243 -0
- data/ext/bytecode/nominal-ping.mtl +5828 -0
- data/ext/mtl/Makefile +42 -0
- data/ext/mtl/README.md +13 -0
- data/ext/mtl/bc.cpp +1891 -0
- data/ext/mtl/conf.bin.sans_password +0 -0
- data/ext/mtl/config.txt +5 -0
- data/ext/mtl/dumpbc.c +2566 -0
- data/ext/mtl/extconf.rb +1 -0
- data/ext/mtl/linux_simu.c +271 -0
- data/ext/mtl/linux_simuaudio.c +16 -0
- data/ext/mtl/linux_simuaudio.h +18 -0
- data/ext/mtl/linux_simunet.c +620 -0
- data/ext/mtl/linux_simunet.h +7 -0
- data/ext/mtl/log.c +297 -0
- data/ext/mtl/log.h +20 -0
- data/ext/mtl/main_compiler.cpp +104 -0
- data/ext/mtl/main_simu.cpp +221 -0
- data/ext/mtl/mp3/GTKANAL.H +97 -0
- data/ext/mtl/mp3/LAYER3.C +2090 -0
- data/ext/mtl/mp3/TABINIT.C +82 -0
- data/ext/mtl/mp3/common.c +265 -0
- data/ext/mtl/mp3/dct64_i386.c +316 -0
- data/ext/mtl/mp3/decode_i386.c +155 -0
- data/ext/mtl/mp3/huffman.h +332 -0
- data/ext/mtl/mp3/interface.c +258 -0
- data/ext/mtl/mp3/mpg123.h +182 -0
- data/ext/mtl/mp3/mpglib.h +44 -0
- data/ext/mtl/properties.c +293 -0
- data/ext/mtl/properties.h +10 -0
- data/ext/mtl/simu.c +750 -0
- data/ext/mtl/simuaudio.c +662 -0
- data/ext/mtl/simuaudio.h +74 -0
- data/ext/mtl/simunet.c +400 -0
- data/ext/mtl/simunet.h +30 -0
- data/ext/mtl/utils/correct_const.sh +34 -0
- data/ext/mtl/vaudio.c +677 -0
- data/ext/mtl/vaudio.h +46 -0
- data/ext/mtl/vbc.h +160 -0
- data/ext/mtl/vbc_str.h +166 -0
- data/ext/mtl/vcomp/Makefile +29 -0
- data/ext/mtl/vcomp/bootstrap.cpp +89 -0
- data/ext/mtl/vcomp/compiler.cpp +470 -0
- data/ext/mtl/vcomp/compiler.h +200 -0
- data/ext/mtl/vcomp/compiler_file.cpp +929 -0
- data/ext/mtl/vcomp/compiler_prog.cpp +250 -0
- data/ext/mtl/vcomp/compiler_term.cpp +1053 -0
- data/ext/mtl/vcomp/compiler_type.cpp +872 -0
- data/ext/mtl/vcomp/compiler_var.cpp +289 -0
- data/ext/mtl/vcomp/file.cpp +79 -0
- data/ext/mtl/vcomp/file.h +39 -0
- data/ext/mtl/vcomp/filesystem.h +14 -0
- data/ext/mtl/vcomp/interpreter.cpp +85 -0
- data/ext/mtl/vcomp/interpreter.h +121 -0
- data/ext/mtl/vcomp/memory.cpp +241 -0
- data/ext/mtl/vcomp/memory.h +326 -0
- data/ext/mtl/vcomp/param.h +95 -0
- data/ext/mtl/vcomp/parser.cpp +427 -0
- data/ext/mtl/vcomp/parser.h +97 -0
- data/ext/mtl/vcomp/parser_xml.cpp +124 -0
- data/ext/mtl/vcomp/prodbuffer.cpp +125 -0
- data/ext/mtl/vcomp/prodbuffer.h +42 -0
- data/ext/mtl/vcomp/resource.h +17 -0
- data/ext/mtl/vcomp/stdlib_core.cpp +122 -0
- data/ext/mtl/vcomp/terminal.cpp +73 -0
- data/ext/mtl/vcomp/terminal.h +30 -0
- data/ext/mtl/vcomp/util.cpp +48 -0
- data/ext/mtl/vcomp/util.h +31 -0
- data/ext/mtl/vinterp.c +1349 -0
- data/ext/mtl/vinterp.h +11 -0
- data/ext/mtl/vloader.c +127 -0
- data/ext/mtl/vloader.h +31 -0
- data/ext/mtl/vlog.c +589 -0
- data/ext/mtl/vlog.h +69 -0
- data/ext/mtl/vmem.c +424 -0
- data/ext/mtl/vmem.h +107 -0
- data/ext/mtl/vnet.c +255 -0
- data/ext/mtl/vnet.h +19 -0
- data/lib/nabaztag_hack_kit/message/api.rb +39 -0
- data/lib/nabaztag_hack_kit/message/helper.rb +39 -0
- data/lib/nabaztag_hack_kit/message.rb +36 -0
- data/lib/nabaztag_hack_kit/server.rb +50 -0
- data/lib/nabaztag_hack_kit/version.rb +3 -0
- data/lib/nabaztag_hack_kit.rb +4 -0
- data/nabaztag_hack_kit.gemspec +29 -0
- data/public/bytecode.bin +0 -0
- data/test/bytecode/helper.mtl +60 -0
- data/test/bytecode/native.mtl +28 -0
- data/test/bytecode/test.mtl +221 -0
- data/test/spec_helper.rb +5 -0
- data/test/unit/message_spec.rb +56 -0
- metadata +209 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
# Nabaztag Hack Kit
|
2
|
+
|
3
|
+
Everything you need to hack the Rabbit: a sinatra server including simple api framework to run custom bytecode on Nabaztag v1/v2. Sources + Compiler included (linux only)
|
4
|
+
|
5
|
+
![](http://travis-ci.org/rngtng/NabaztagHackKit.png)
|
6
|
+
|
7
|
+
## Getting Started
|
8
|
+
|
9
|
+
### Compile & Run
|
10
|
+
|
11
|
+
The kit comes with violet sources and binaries to compile custom Nabaztag bytecode. On a linux machine those binaries are compiled on instalation of the gem. Following three binaries are available:
|
12
|
+
|
13
|
+
#### mtl_merge
|
14
|
+
|
15
|
+
Merges multiple `*.mtl` files into one. Files are included like in C: `#include "<relative path to file>"`. Output is temporary file `.tmp.mtl`.
|
16
|
+
|
17
|
+
#### mtl_comp
|
18
|
+
|
19
|
+
Compiles a `*.mtl` file. It calls `mtl_merge` before, and fallbacks to remote compiler in case binary is not found and `HOST` is given.
|
20
|
+
|
21
|
+
#### mtl_simu
|
22
|
+
|
23
|
+
Runs a `*.mtl` file. It calls `mtl_merge` before, and fallbacks to remote simulator in case binary is not found and `HOST` is given.
|
24
|
+
|
25
|
+
|
26
|
+
### Understanding the Bytecode
|
27
|
+
|
28
|
+
The bytecode is written in a custom language by Sylvain Huet. Its referenced as _Metal_ and files end with `.mtl`. Unfortunately documentation is very poor (and in french). Check directory `ext/bytecode/` which contains a basic overview & documentaion as well as a list of (common) commands. A good reference is the original bytecode, included in the directory as well. Major parts got extracted into seperate files, found in `lib/` directory and ready to be included in your code.
|
29
|
+
|
30
|
+
### Testing
|
31
|
+
|
32
|
+
The kit includes a simple test framework to test custom bytecode. See `test/bytecode/test.mtl`. A typical test looks like this:
|
33
|
+
|
34
|
+
```c
|
35
|
+
let test "<test name>" -> t in
|
36
|
+
(
|
37
|
+
//assertions
|
38
|
+
assert_equalI 0 10 - (2* 5);
|
39
|
+
0);
|
40
|
+
```
|
41
|
+
|
42
|
+
The framework offers assertions similar to ruby tunit stile. Mind that the variable type has to be given
|
43
|
+
explicit. Convertion is:
|
44
|
+
|
45
|
+
* I = interger
|
46
|
+
* S = string
|
47
|
+
* L = list
|
48
|
+
* T = tab
|
49
|
+
|
50
|
+
Following assertions are available:
|
51
|
+
|
52
|
+
* assert_equalI I I
|
53
|
+
* assert_equalI S S
|
54
|
+
* assert_nil I
|
55
|
+
* assert_equalIL
|
56
|
+
* assert_equalSL
|
57
|
+
* assert_equalTL
|
58
|
+
|
59
|
+
|
60
|
+
## Server
|
61
|
+
|
62
|
+
The Server is the communication endpoint for the rabbit. Its two main purposes are:
|
63
|
+
|
64
|
+
1. serving the bytecode on bootup
|
65
|
+
2. receive and respond to HTTP requests in a defined format.
|
66
|
+
|
67
|
+
To start the server, run shortcut `rake run` or, as it's based on rack, `rackup -p <portnumer>`.
|
68
|
+
|
69
|
+
|
70
|
+
## API
|
71
|
+
As example and for my own purposes I implemented a simple API to deal with RFID, LEDS, BUTTON and EARS easily.
|
72
|
+
|
73
|
+
### Input Devices
|
74
|
+
|
75
|
+
#### RFID
|
76
|
+
NabaztagInjector
|
77
|
+
|
78
|
+
|
79
|
+
#### BUTTON
|
80
|
+
Current Button has very basic functionality: a short press send HTTP Request of type `Log` to server, a long
|
81
|
+
press foreces the bunny to restart.
|
82
|
+
|
83
|
+
### Output Devices
|
84
|
+
Data for all output devices are stored in buffers. Each device has two: one for ontime, imediate playback, another for permanet loops.
|
85
|
+
|
86
|
+
#### LEDS
|
87
|
+
Buffers 0 - 9, where 0-4 are used for onetime, and 5-9 for loop playback.
|
88
|
+
|
89
|
+
#### EARS
|
90
|
+
Buffers 10 - 13, where 10 & 11 are used for onetime, and 12 & 13 for loop playback.
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
## Disclamer
|
95
|
+
|
96
|
+
The server party was heavily inspired by [Trudy.rb](https://github.com/quimarche/trudy/blob/master/trudy.rb), compiler code copied from OpenJabNab.
|
97
|
+
Thanks!
|
98
|
+
|
99
|
+
|
100
|
+
### Protocol
|
101
|
+
A good introduction to understand Nabaztag Protocol:
|
102
|
+
|
103
|
+
* http://www.cs.uta.fi/hci/spi/jnabserver/documentation/index.html
|
104
|
+
|
105
|
+
|
106
|
+
### Nabaztag Background
|
107
|
+
Read following posting for more backgorund on Nabaztag Hacking (uses google translate:)
|
108
|
+
|
109
|
+
* [Les source bytecode et compilateur](http://translate.googleusercontent.com/translate_c?hl=en&rurl=translate.google.com&sl=fr&tl=en&twu=1&u=http://nabaztag.forumactif.fr/t13241p30-les-sources-bytecode-et-compilateur&usg=ALkJrhjLTbx1GMfSUgwhdjES1LzlE07HZQ#338060)
|
110
|
+
* [Mindscape donne une seconde vie a nabaztag](http://translate.google.com/translate?hl=en&sl=fr&tl=en&u=http%3A%2F%2Fwww.planete-domotique.com%2Fblog%2F2011%2F08%2F07%2Fmindscape-donne-une-seconde-vie-a-nabaztag%2F)
|
111
|
+
|
112
|
+
|
113
|
+
### Future
|
114
|
+
I'd like to hack the Violet mir:ror too. Some starting points:
|
115
|
+
|
116
|
+
* https://github.com/leh/ruby-mirror
|
117
|
+
* http://reflektor.sourceforge.net/
|
118
|
+
|
119
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
RSpec::Core::RakeTask.new("unit") do |t|
|
5
|
+
t.pattern = "./test/**/*_spec.rb" # don't need this, it's default.
|
6
|
+
end
|
7
|
+
|
8
|
+
namespace :test do
|
9
|
+
desc "Test bytcode"
|
10
|
+
task :bytecode do
|
11
|
+
puts `bin/mtl_simu test/bytecode/test.mtl`
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
task :test => [:unit]
|
16
|
+
task :default => :test
|
17
|
+
|
18
|
+
desc "start server on port 9090"
|
19
|
+
task :run do
|
20
|
+
`rackup -p 9090`
|
21
|
+
end
|
data/bin/mtl_comp
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
BIN_NAME = File.basename(__FILE__)
|
4
|
+
BIN_PATH = File.dirname(__FILE__)
|
5
|
+
BIN = File.join( File.expand_path("../ext/mtl", BIN_PATH), BIN_NAME)
|
6
|
+
FILE = ARGV.first
|
7
|
+
|
8
|
+
FILTER = ENV['FILTER'] || "| grep -v 'bytes' | grep -e'[a-z]'"
|
9
|
+
MERGE = File.join(BIN_PATH, 'mtl_merge')
|
10
|
+
TMP = ENV['TMP'] || '.tmp.mtl'
|
11
|
+
OUT = ENV['OUT'] || "bytecode.bin"
|
12
|
+
|
13
|
+
HOST = ENV['HOST']
|
14
|
+
REMOTE_PATH = ENV['REMOTE'] || "~/"
|
15
|
+
REMOTE_BIN = ENV['REMOTE_BIN']
|
16
|
+
|
17
|
+
unless FILE
|
18
|
+
puts "usage: #{File.basename(__FILE__)} [filename]"
|
19
|
+
abort
|
20
|
+
end
|
21
|
+
|
22
|
+
# merge
|
23
|
+
`TMP='#{TMP}' #{MERGE} #{FILE}`
|
24
|
+
|
25
|
+
# compile
|
26
|
+
out = nil
|
27
|
+
if File.exists?(BIN)
|
28
|
+
out = `#{BIN} -s #{FILE} #{OUT} 2>&1 #{FILTER}`
|
29
|
+
else
|
30
|
+
print "local binary not found"
|
31
|
+
end
|
32
|
+
|
33
|
+
if HOST
|
34
|
+
puts " - falling back to remote"
|
35
|
+
`scp #{TMP} #{HOST}:#{REMOTE_PATH}#{TMP}`
|
36
|
+
out = `ssh #{HOST} "cd #{REMOTE_PATH} && rm -f #{TMP}.bin && #{REMOTE_BIN}#{BIN_NAME} -s #{TMP} #{TMP}.bin 2>&1 #{FILTER}"`
|
37
|
+
`scp #{HOST}:#{REMOTE_PATH}#{TMP}.bin #{OUT}`
|
38
|
+
end
|
39
|
+
|
40
|
+
puts out
|
41
|
+
`rm #{TMP}`
|
data/bin/mtl_merge
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Merge a file with its includes, pass filename as first argument
|
4
|
+
|
5
|
+
TMP = ENV['TMP'] || '.tmp.mtl'
|
6
|
+
|
7
|
+
unless ARGV.size == 1
|
8
|
+
puts "usage: #{File.basename(__FILE__)} [filename]"
|
9
|
+
abort
|
10
|
+
end
|
11
|
+
|
12
|
+
file = ARGV.first
|
13
|
+
|
14
|
+
dir = File.dirname(file)
|
15
|
+
File.open(TMP, 'w') do |out|
|
16
|
+
File.open(file).each_line do |line|
|
17
|
+
if line =~ /#include "([^"]+)"/
|
18
|
+
line = `cat #{dir}/#{$1}.mtl`
|
19
|
+
end
|
20
|
+
out.puts line
|
21
|
+
end
|
22
|
+
end
|
data/bin/mtl_simu
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
BIN_NAME = File.basename(__FILE__)
|
4
|
+
BIN_PATH = File.dirname(__FILE__)
|
5
|
+
BIN = File.join( File.expand_path("../ext/mtl", BIN_PATH), BIN_NAME)
|
6
|
+
FILE = ARGV.first
|
7
|
+
|
8
|
+
FILTER = ENV['FILTER'] || "| grep -v 'bytes' | grep -e'[a-z]'"
|
9
|
+
MERGE = File.join(BIN_PATH, 'mtl_merge')
|
10
|
+
TMP = ENV['TMP'] || '.tmp.mtl'
|
11
|
+
OUT = ENV['OUT'] || "bytecode.bin"
|
12
|
+
|
13
|
+
HOST = ENV['HOST']
|
14
|
+
REMOTE_PATH = ENV['REMOTE'] || "~/"
|
15
|
+
REMOTE_BIN = ENV['REMOTE_BIN']
|
16
|
+
|
17
|
+
unless FILE
|
18
|
+
puts "usage: #{File.basename(__FILE__)} [filename]"
|
19
|
+
abort
|
20
|
+
end
|
21
|
+
|
22
|
+
# merge
|
23
|
+
`TMP='#{TMP}' #{MERGE} #{FILE}`
|
24
|
+
|
25
|
+
# simu
|
26
|
+
out = nil
|
27
|
+
if File.exists?(BIN)
|
28
|
+
out = `#{BIN} -s #{FILE} #{OUT} 2>&1 #{FILTER}`
|
29
|
+
else
|
30
|
+
print "local binary not found"
|
31
|
+
end
|
32
|
+
|
33
|
+
if HOST
|
34
|
+
puts " - falling back to remote"
|
35
|
+
`scp #{TMP} #{HOST}:#{REMOTE_PATH}#{TMP}`
|
36
|
+
out = `ssh #{HOST} "cd #{REMOTE_PATH} && #{REMOTE_BIN}#{BIN_NAME} --source #{TMP} < #{TMP} 1>&2"`
|
37
|
+
end
|
38
|
+
|
39
|
+
puts out
|
40
|
+
`rm #{TMP}`
|
@@ -0,0 +1,109 @@
|
|
1
|
+
//###############################################
|
2
|
+
//---------------------- Buffer -------------------------------
|
3
|
+
|
4
|
+
var buffers;;
|
5
|
+
type BUFFER=[valB stepB lenB posB loopB];;
|
6
|
+
|
7
|
+
fun buffersInit len=
|
8
|
+
set buffers = tabnew nil len;
|
9
|
+
for index = 0; index < len; index + 1 do
|
10
|
+
set buffers.index = [valB:""]
|
11
|
+
;;
|
12
|
+
|
13
|
+
fun _bufferFill index step loop val=
|
14
|
+
let strlen val -> len in
|
15
|
+
set buffers.index = [valB:val stepB:step lenB:len posB:0 loopB:loop];
|
16
|
+
0;;
|
17
|
+
|
18
|
+
fun bufferFill index val=
|
19
|
+
_bufferFill index 1 0 val
|
20
|
+
;;
|
21
|
+
|
22
|
+
fun bufferFill3 index val=
|
23
|
+
_bufferFill index 3 0 val
|
24
|
+
;;
|
25
|
+
|
26
|
+
fun loopBufferFill index val=
|
27
|
+
_bufferFill index 1 1 val
|
28
|
+
;;
|
29
|
+
|
30
|
+
fun loopBufferFill3 index val=
|
31
|
+
_bufferFill index 3 1 val
|
32
|
+
;;
|
33
|
+
|
34
|
+
fun buffersFill from to val=
|
35
|
+
for index = from; index <= to; index + 1 do
|
36
|
+
bufferFill index val
|
37
|
+
;;
|
38
|
+
|
39
|
+
fun buffersFill3 from to val=
|
40
|
+
for index = from; index <= to; index + 1 do
|
41
|
+
bufferFill3 index val
|
42
|
+
;;
|
43
|
+
|
44
|
+
fun bufferRead index=
|
45
|
+
let buffers.index -> buffer in
|
46
|
+
if buffer.posB < buffer.lenB then
|
47
|
+
(
|
48
|
+
set buffer.posB = buffer.posB + buffer.stepB;
|
49
|
+
let buffer.posB - buffer.stepB -> pos in
|
50
|
+
if buffer.stepB == 3 then
|
51
|
+
CtoI3 buffer.valB pos
|
52
|
+
else
|
53
|
+
strget buffer.valB pos
|
54
|
+
) else if buffer.loopB > 0 && buffer.posB > 0 then (
|
55
|
+
set buffer.posB = 0;
|
56
|
+
bufferRead index
|
57
|
+
)
|
58
|
+
else (
|
59
|
+
nil
|
60
|
+
)
|
61
|
+
;;
|
62
|
+
|
63
|
+
//-----------------------------------------------------
|
64
|
+
var palette = {0 90 130 170 215 255 255 255};; // 0x00 0x5a 0x82 0xaa 0xd7 0xFF
|
65
|
+
|
66
|
+
fun COtoI r g b=
|
67
|
+
r * 36 + g * 6 + b
|
68
|
+
;;
|
69
|
+
|
70
|
+
fun ItoCO val=
|
71
|
+
if val == nil then set val = 0;
|
72
|
+
if val > 215 then set val = 215;
|
73
|
+
let val / 36 -> r in
|
74
|
+
let (val % 36) / 6 -> g in
|
75
|
+
let (val % 36) % 6 -> b in
|
76
|
+
palette.r << 16 + palette.g << 8 + palette.b
|
77
|
+
;;
|
78
|
+
|
79
|
+
// returns number of chars before char \255
|
80
|
+
fun str_find_end val=
|
81
|
+
strstr val "\255" 0
|
82
|
+
;;
|
83
|
+
|
84
|
+
//-----------------------------------------------------
|
85
|
+
const RESPONSE_HEADER = 0x7f;;
|
86
|
+
|
87
|
+
fun parseResponse_ s i res=
|
88
|
+
if (i < strlen s) then
|
89
|
+
(
|
90
|
+
let (strget s i) -> code in
|
91
|
+
let (CtoI3 s i+1) -> len in
|
92
|
+
(
|
93
|
+
if len >= 0 then
|
94
|
+
(
|
95
|
+
let strsub s i+4 len -> data in
|
96
|
+
parseResponse_ s i+4+len [code data]::res
|
97
|
+
)
|
98
|
+
)
|
99
|
+
)
|
100
|
+
else (
|
101
|
+
res
|
102
|
+
)
|
103
|
+
;;
|
104
|
+
|
105
|
+
// messages will be reveresed!
|
106
|
+
fun parseResponse s=
|
107
|
+
if (strget s 0) == RESPONSE_HEADER then
|
108
|
+
parseResponse_ s 1 nil
|
109
|
+
;;
|
@@ -0,0 +1,27 @@
|
|
1
|
+
//###############################################
|
2
|
+
//------------------- Button --------------------
|
3
|
+
|
4
|
+
const BUTTON_REBOOT = 30;; //ms MIN 50ms
|
5
|
+
var button_pressed = 0;;
|
6
|
+
fun checkButton=
|
7
|
+
if (button2 > 0) then
|
8
|
+
(
|
9
|
+
set button_pressed = button_pressed + 1;
|
10
|
+
if button_pressed == 1 then
|
11
|
+
(
|
12
|
+
httprequest "GET" buttonUrl (itoa time_ms) "" #_cbHttp HTTP_NORMAL;
|
13
|
+
0
|
14
|
+
) else if button_pressed == BUTTON_REBOOT then
|
15
|
+
(
|
16
|
+
buffersFill 0 4 "\0\255\0\255\0\255\255\255"
|
17
|
+
)
|
18
|
+
)
|
19
|
+
//reboot only when button not pressed, otherwise we get into setup mode
|
20
|
+
else if button_pressed > BUTTON_REBOOT then
|
21
|
+
(
|
22
|
+
exit
|
23
|
+
)
|
24
|
+
else (
|
25
|
+
set button_pressed = 0
|
26
|
+
)
|
27
|
+
;;
|
@@ -0,0 +1,88 @@
|
|
1
|
+
var logs = "";;
|
2
|
+
|
3
|
+
fun log t tab=
|
4
|
+
let "|"::nil -> all in
|
5
|
+
(
|
6
|
+
for i = tablen tab; i > 0 ; i - 1 do
|
7
|
+
(
|
8
|
+
let itoa tab.(i - 1) -> data in
|
9
|
+
set all = data::","::all
|
10
|
+
);
|
11
|
+
set logs = strcatlist logs::t::","::(itoa time_ms)::","::all
|
12
|
+
)
|
13
|
+
;;
|
14
|
+
|
15
|
+
fun TLtoS tlist=
|
16
|
+
if tlist == nil then
|
17
|
+
""
|
18
|
+
else
|
19
|
+
let hd tlist -> [a b] in
|
20
|
+
strcatlist (itoa a)::b::(TLtoS tl tlist)::nil
|
21
|
+
;;
|
22
|
+
|
23
|
+
//----------- Data Dump
|
24
|
+
|
25
|
+
// echo a string list as string
|
26
|
+
fun SLecho list=
|
27
|
+
Secho strcatlist list
|
28
|
+
;;
|
29
|
+
|
30
|
+
fun SLecholn list=
|
31
|
+
SLecho list;
|
32
|
+
Secholn ""
|
33
|
+
;;
|
34
|
+
|
35
|
+
// echo a integer list as string
|
36
|
+
fun ILecho list=
|
37
|
+
Secho listtostr list
|
38
|
+
;;
|
39
|
+
|
40
|
+
fun ILecholn list=
|
41
|
+
ILecho list;
|
42
|
+
Secholn ""
|
43
|
+
;;
|
44
|
+
|
45
|
+
fun TLecho tlist=
|
46
|
+
Secho TLtoS tlist
|
47
|
+
;;
|
48
|
+
|
49
|
+
//----------- Data Transformation
|
50
|
+
|
51
|
+
// string to list of hex chars
|
52
|
+
fun _webmac key i=
|
53
|
+
if i < strlen key then (ctoh strget key i)::_webmac key i+1;;
|
54
|
+
fun webmac key=
|
55
|
+
strcatlist _webmac key 0;;
|
56
|
+
|
57
|
+
//convert chars into int (there is a limit!!!)
|
58
|
+
fun _StoI val pos len=
|
59
|
+
let strget val pos -> v in
|
60
|
+
if(len >= 0) then
|
61
|
+
v << (8 * len) + _StoI val (pos + 1) (len - 1)
|
62
|
+
else
|
63
|
+
0
|
64
|
+
;;
|
65
|
+
fun StoI val=
|
66
|
+
_StoI val 0 (strlen val) - 1
|
67
|
+
;;
|
68
|
+
|
69
|
+
//convert first 3 chars into int (perfect to set led color)
|
70
|
+
fun StoI3 val=
|
71
|
+
_StoI val 0 2
|
72
|
+
;;
|
73
|
+
|
74
|
+
//convert first 2 chars into int (perfect to set led color)
|
75
|
+
fun StoI2 val=
|
76
|
+
_StoI val 0 1
|
77
|
+
;;
|
78
|
+
|
79
|
+
fun CtoI3 s offset=
|
80
|
+
(strget s offset) << 16 + (strget s offset+1) << 8 + strget s offset+2
|
81
|
+
;;
|
82
|
+
|
83
|
+
// -------------------- other stuff
|
84
|
+
|
85
|
+
fun exit=
|
86
|
+
Secholn "\n";
|
87
|
+
reboot 0x0407FE58 0x13fb6754
|
88
|
+
;;
|
@@ -0,0 +1,90 @@
|
|
1
|
+
//###############################################
|
2
|
+
//------------------- EAR -----------------------
|
3
|
+
|
4
|
+
var ears;;
|
5
|
+
const EAR_INIT = nil;;
|
6
|
+
const EAR_STOP = 0;;
|
7
|
+
const EAR_FORWARD = 1;;
|
8
|
+
const EAR_BACKWARD = -1;;
|
9
|
+
const EAR_TICKS = 17;;
|
10
|
+
|
11
|
+
type EAR=[dir pos shouldPos lastOffset lastTime lastTime2 lastRead];;
|
12
|
+
|
13
|
+
fun earNorm norm=
|
14
|
+
(EAR_TICKS + norm) % EAR_TICKS
|
15
|
+
;;
|
16
|
+
|
17
|
+
fun earBufferRead index=
|
18
|
+
let bufferRead index+10 -> earPos in
|
19
|
+
(
|
20
|
+
if earPos != nil then
|
21
|
+
set earPos = earNorm earPos;
|
22
|
+
earPos
|
23
|
+
)
|
24
|
+
;;
|
25
|
+
|
26
|
+
fun earRead index=
|
27
|
+
let ears.index -> ear in
|
28
|
+
let time_ms -> currentTime in
|
29
|
+
(
|
30
|
+
let motorget index -> currentOffset in
|
31
|
+
let (currentOffset - ear.lastOffset) -> diff in
|
32
|
+
(
|
33
|
+
if diff > 0 then //ear moved
|
34
|
+
(
|
35
|
+
// update pos
|
36
|
+
if ear.pos != EAR_INIT then
|
37
|
+
let ear.dir -> direction in
|
38
|
+
(
|
39
|
+
if direction == 0 then set direction = 1; //manual moved!!
|
40
|
+
set ear.pos = earNorm ear.pos + direction * diff
|
41
|
+
);
|
42
|
+
|
43
|
+
// check for reset Reset
|
44
|
+
let currentTime - ear.lastTime -> lastDuration in
|
45
|
+
let currentTime - ear.lastTime2 -> totalDuration in
|
46
|
+
if ear.dir != EAR_STOP && lastDuration > 1000 && totalDuration < 1450 then
|
47
|
+
(
|
48
|
+
set ear.pos = earNorm (ear.dir - 1) / 2; // either 0 or 16
|
49
|
+
bufferFill 0 "\100";
|
50
|
+
log "reset" {index lastDuration totalDuration ear.dir ear.pos}
|
51
|
+
);
|
52
|
+
log "moved" {index ear.lastTime ear.lastTime2 ear.lastRead ear.pos ear.shouldPos ear.dir };
|
53
|
+
|
54
|
+
set ear.lastTime2 = ear.lastTime;
|
55
|
+
set ear.lastTime = currentTime
|
56
|
+
);
|
57
|
+
set ear.lastOffset = currentOffset
|
58
|
+
);
|
59
|
+
|
60
|
+
// check & read new value
|
61
|
+
if (ear.pos != EAR_INIT) && (ear.pos == ear.shouldPos) && (currentTime - ear.lastRead) > 270 then
|
62
|
+
(
|
63
|
+
let earBufferRead index -> earPos in
|
64
|
+
(
|
65
|
+
if earPos == nil then set earPos = earBufferRead index+2;
|
66
|
+
if earPos == nil then set earPos = ear.pos;
|
67
|
+
set ear.shouldPos = earPos;
|
68
|
+
set ear.dir = earNorm ear.shouldPos - ear.pos;
|
69
|
+
if ear.dir > 8 then set ear.dir = -1;
|
70
|
+
if ear.dir > 0 then set ear.dir = 1;
|
71
|
+
motorset index ear.dir;
|
72
|
+
|
73
|
+
set ear.lastRead = currentTime
|
74
|
+
|
75
|
+
// log "ear read" {index time_ms earPos ear.pos ear.shouldPos}
|
76
|
+
)
|
77
|
+
)
|
78
|
+
)
|
79
|
+
;;
|
80
|
+
|
81
|
+
fun earsInit=
|
82
|
+
let time_ms -> currentT in
|
83
|
+
(
|
84
|
+
set ears = tabnew nil 2;
|
85
|
+
set ears.0 = [dir:EAR_FORWARD pos:EAR_INIT shouldPos:0 lastTime:currentT lastTime2:currentT];
|
86
|
+
set ears.1 = [dir:EAR_FORWARD pos:EAR_INIT shouldPos:0 lastTime:currentT lastTime2:currentT];
|
87
|
+
motorset 0 1;
|
88
|
+
motorset 1 1
|
89
|
+
);
|
90
|
+
0;;
|
@@ -0,0 +1,33 @@
|
|
1
|
+
//###############################################
|
2
|
+
//------------------ LED ----------------------
|
3
|
+
|
4
|
+
const LED_CHECK_FQ = 500;; //ms MIN 50ms
|
5
|
+
var led_last_check = 0;;
|
6
|
+
|
7
|
+
fun ledBufferRead index=
|
8
|
+
let bufferRead index -> color in
|
9
|
+
let buffers.index -> buffer in
|
10
|
+
if color != nil && buffer.stepB == 1 then
|
11
|
+
ItoCO color
|
12
|
+
else
|
13
|
+
color
|
14
|
+
;;
|
15
|
+
|
16
|
+
fun setLeds=
|
17
|
+
//LED_CHECK_FQ
|
18
|
+
let (button3 + 1) * 3 -> led_check_fq in
|
19
|
+
if ((time_ms - led_last_check) > led_check_fq) then
|
20
|
+
(
|
21
|
+
for index = 0; index < 5; index + 1 do
|
22
|
+
(
|
23
|
+
let ledBufferRead index+5 -> loopColor in
|
24
|
+
let ledBufferRead index -> color in
|
25
|
+
(
|
26
|
+
if color == nil then set color = loopColor;
|
27
|
+
if color == nil then set color = 0;
|
28
|
+
led index color
|
29
|
+
)
|
30
|
+
);
|
31
|
+
set led_last_check = time_ms
|
32
|
+
)
|
33
|
+
;;
|
@@ -0,0 +1,50 @@
|
|
1
|
+
//###############################################
|
2
|
+
//--------------- RFID ------------------------
|
3
|
+
|
4
|
+
const RFID_CHECK_FQ = 500;; //ms MIN 50ms
|
5
|
+
const RFID_STOP_BYTE = 0xFF;;
|
6
|
+
const RFID_ID_START = "\208\2\26";; // 0xd0 0x02 0x1a
|
7
|
+
const RFID_ID_FALSE = "\0\0\0\0\0\0\0\0\v";;
|
8
|
+
const RFID_ID_ERROR = "\69\114\114\111\114\0\0\0\v";; // 0x45 72 72 6f 72 00 00 00
|
9
|
+
|
10
|
+
var rfid_last_check = 0;;
|
11
|
+
var rfid_data = "";;
|
12
|
+
|
13
|
+
fun checkRFID=
|
14
|
+
if ((time_ms - rfid_last_check) > RFID_CHECK_FQ) then
|
15
|
+
(
|
16
|
+
let rfidGet -> rfid in
|
17
|
+
if (rfid != nil) then
|
18
|
+
(
|
19
|
+
if ((strstr rfid RFID_ID_START 0) == 0) then
|
20
|
+
(
|
21
|
+
httprequest "PUT" playerUrl rfid "" #_cbHttp HTTP_NORMAL;
|
22
|
+
0
|
23
|
+
)
|
24
|
+
else if ((strstr rfid RFID_ID_FALSE 0) == 0) then
|
25
|
+
(
|
26
|
+
0
|
27
|
+
)
|
28
|
+
else
|
29
|
+
(
|
30
|
+
let strlen rfid -> len in //usually that's 8
|
31
|
+
for index = 0; index < len; index + 1 do
|
32
|
+
(
|
33
|
+
let strget rfid index -> data_byte in
|
34
|
+
(
|
35
|
+
if (data_byte != RFID_STOP_BYTE) then
|
36
|
+
set rfid_data = strcat rfid_data ctoh data_byte
|
37
|
+
else if ((strlen rfid_data) > 0) then
|
38
|
+
(
|
39
|
+
httprequest "POST" eventUrl rfid_data "" #_cbHttp HTTP_NORMAL;
|
40
|
+
set rfid_data = ""
|
41
|
+
)
|
42
|
+
)
|
43
|
+
);
|
44
|
+
0
|
45
|
+
)
|
46
|
+
);
|
47
|
+
//all done
|
48
|
+
set rfid_last_check = time_ms
|
49
|
+
);
|
50
|
+
0;;
|