nabaztag_hack_kit 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+

|
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;;
|