blob: eb37e915227642e95652d0b0a78d04b4a0ef98b8 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
#lang racket/base
(require racket/list
(planet lizorkin/sxml:2:1/sxml)
(planet lizorkin/ssax:2:0/ssax)
"layer2.rkt")
(define logger (make-logger 'ebus-layer7 (current-logger)))
(define definition
(ssax:xml->sxml (open-input-file "../ebus-xml/ebus.xml")
'[(#f . "http://xapek.org/ebus/0.1")]))
(define (paket ebus-paket)
(define primaryCommand (layer2-ebus-paket-primaryCommand ebus-paket))
(define secondaryCommand (layer2-ebus-paket-secondaryCommand ebus-paket))
((sxpath (string-append "//packet[@primary=" (number->string primaryCommand)
" and @secondary=" (number->string secondaryCommand) "]"))
definition))
;; returns the full device-definition
(define (device address)
((sxpath (string-append "//devices/device[@address=" (number->string address) "]"))
definition))
;; returns device-name in a list or empty-list
(define (device-name address)
(first ((sxpath "@name/text()") (device address))))
(define (paket-fields ebus-paket)
(define paket-definition (paket ebus-paket))
(cond ((> (length paket-definition) 0)
(let*
([paket-name (string-append
(device-name (layer2-ebus-paket-source ebus-paket))
"."
(first ((sxpath "@name/text()") paket-definition)))]
[fields ((sxpath "fields/*") paket-definition)]
[values
(for/list ([field fields]) (paket-fields-dispatch-decoder ebus-paket field paket-name))])
;; filter invalid values
(for/list ([value values] #:when (not (void? value)))
value)))
(else (void (log-message logger 'warning (format "Unknown Paket: ~s" ebus-paket) #t)))))
(define (paket-fields-dispatch-decoder ebus-paket field paket-name)
(define datatype ((sxpath "name()") field))
(define name (string-append paket-name "." (first ((sxpath "@name/text()") field))))
(define offset (string->number (first ((sxpath "@offset/text()") field))))
(define payload (layer2-ebus-paket-payload ebus-paket))
(cond ((string=? "bit" datatype)
(list name datatype offset
(field-decoder-bit (list-ref payload offset))))
((string=? "bcd" datatype)
(list name datatype offset
(field-decoder-bcd (list-ref payload offset))))
((string=? "data1b" datatype)
(list name datatype offset
(field-decoder-data1b (list-ref payload offset))))
((string=? "data1c" datatype)
(list name datatype offset
(field-decoder-data1c (list-ref (layer2-ebus-paket-payload ebus-paket) offset))))
((string=? "byte" datatype)
(list name datatype offset (list-ref payload offset)))
((string=? "data2b" datatype)
(list name datatype offset
(field-decoder-data2b (list-ref payload offset)
(list-ref payload (+ offset 1)))))
((string=? "data2c" datatype)
(list name datatype offset
(field-decoder-data2c (list-ref payload offset)
(list-ref payload (+ offset 1)))))
((string=? "word" datatype)
(list name datatype offset
(field-decoder-word (list-ref payload offset)
(list-ref payload (+ offset 1)))))
((string=? "byteEnum" datatype)
(list name datatype offset
(field-decoder-byteEnum (list-ref payload offset) field)))
(else (void (log-message logger 'error (format "unknown datatype: ~a" datatype) #t)))))
;; type bit
(define (field-decoder-bit value)
(cond ((= value 1) 1)
(else 0)))
;; type data1b
(define (field-decoder-data1b value)
value)
;; type data1c
(define (field-decoder-data1c value)
(/ value 2.0))
;; type data2b
(define (field-decoder-data2b lowByte highByte)
(if (= (bitwise-and highByte 128) 128)
(* -1
(+ (+ 256 (bitwise-not highByte))
(/ (+ 256 (bitwise-not (+ lowByte 1))) 256.0)))
(+ highByte (/ lowByte 256.0))))
;; type data2c
(define (field-decoder-data2c lowByte highByte)
(define (lowNibble v)
(bitwise-and v #x0f))
(define (highNibble v)
(arithmetic-shift v -4))
(define (u-not v)
(+ 256 (bitwise-not v)))
(if (= (bitwise-and highByte 128) 128)
(* -1
(+ (* 16 (u-not highByte))
(highNibble (u-not lowByte))
(/ (lowNibble (u-not lowByte) 16))))
(+ (* 16 (u-not highByte))
(highNibble lowByte)
(/ (lowNibble lowByte) 16))))
;; type byteEnum
(define (field-decoder-byteEnum value field-definition)
(define (pred l)
(= value (list-ref l 0)))
(define all-options (for/list ([option ((sxpath "option") field-definition)])
(list (string->number (first ((sxpath "@value/text()") option))) ;; value, name
(first ((sxpath "@name/text()") option)))))
(define options (filter pred all-options))
(cond ((= (length options) 1)
(list-ref (first options) 1))
(else "<undefined>")))
;; type word
(define (field-decoder-word lowByte highByte)
(+ lowByte
(arithmetic-shift highByte 8)))
;; type bcd
(define (field-decoder-bcd value)
(+ (bitwise-and value #x0f)
(arithmetic-shift value -4)))
;; read one ebus-paket or eof from input-port
;; or return #<eof>
(define (read-ebus input-port)
(define paket (layer2-read-ebus input-port))
(cond ((layer2-ebus-paket? paket)
(paket-fields paket))
(else paket)))
(provide (prefix-out layer7- paket)
(prefix-out layer7- paket-fields)
(prefix-out layer7- device)
(prefix-out layer7- device-name)
;; read ebus from port an return fields from next paket
(prefix-out layer7- read-ebus)
(prefix-out layer7- logger))
|