tef-furcoms 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +6 -0
- data/lib/tef/furcoms/Base.rb +48 -0
- data/lib/tef/furcoms/MQTT.rb +41 -0
- data/lib/tef/furcoms/Serial.rb +107 -0
- data/lib/tef/furcoms/SerialToMQTT.rb +30 -0
- data/lib/tef/furcoms.rb +3 -0
- metadata +106 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c612206f7e17733552bcca965b3e2684a5ba17c9
|
4
|
+
data.tar.gz: 6bde1a400cb7e6f6fedbe93f50a0ae0550830e1e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bc921df1642b8f5ac7cea97fae3080f40c107621c9ae70a7e51fb42a21e14416a67ff64a2e3899d594da5e6721f688e3e2a1322875c6488d293d8b2280b8becd
|
7
|
+
data.tar.gz: 6a1508a0ec5f87fb9c51e43344987f707faa767caebb3095967eba446fe80d3a8dc539a5da8ee9ab0fa9f74d36cf736c1bd5d0200429dc7673ce34905d6babf1
|
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module TEF
|
4
|
+
module FurComs
|
5
|
+
class Message
|
6
|
+
attr_reader :priority
|
7
|
+
attr_reader :source_id
|
8
|
+
|
9
|
+
attr_reader :topic
|
10
|
+
attr_reader :data
|
11
|
+
|
12
|
+
def initialize()
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Base
|
17
|
+
def initialize()
|
18
|
+
@message_procs = [];
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_message(topic, message, priority: 0, chip_id: 0) end
|
22
|
+
|
23
|
+
def on_message(topic_filter = nil, &block)
|
24
|
+
@message_procs << { topic: topic_filter, block: block };
|
25
|
+
end
|
26
|
+
|
27
|
+
private def handout_data(topic, data)
|
28
|
+
x_logd("Data received on #{topic}: #{data}")
|
29
|
+
|
30
|
+
@message_procs.each do |callback|
|
31
|
+
begin
|
32
|
+
if filter = callback[:topic]
|
33
|
+
if filter.is_a? String
|
34
|
+
next unless topic == filter
|
35
|
+
elsif filter.is_a? RegExp
|
36
|
+
next unless filter.match(topic)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
callback[:block].call(data, topic)
|
41
|
+
rescue => e
|
42
|
+
x_logf("Error in callback #{callback[:block]}: #{e}");
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
require_relative 'Base.rb'
|
3
|
+
|
4
|
+
require 'xasin_logger'
|
5
|
+
|
6
|
+
module TEF
|
7
|
+
module FurComs
|
8
|
+
class MQTT < Base
|
9
|
+
include XasLogger::Mix
|
10
|
+
|
11
|
+
def initialize(mqtt, topic = 'FurComs/ttyACM0/')
|
12
|
+
super();
|
13
|
+
|
14
|
+
@mqtt = mqtt;
|
15
|
+
@mqtt_topic = topic;
|
16
|
+
|
17
|
+
@mqtt.subscribe_to topic + 'Received/#' do |data, topic|
|
18
|
+
topic = topic.join('/')
|
19
|
+
next unless topic =~ /^[\w\s\/]*$/
|
20
|
+
|
21
|
+
handout_data(topic, data);
|
22
|
+
end
|
23
|
+
|
24
|
+
init_x_log(@mqtt_topic)
|
25
|
+
end
|
26
|
+
|
27
|
+
def send_message(topic, data, priority: 0, chip_id: 0)
|
28
|
+
unless topic =~ /^[\w\s\/]*$/
|
29
|
+
raise ArgumentError, "Topic includes invalid characters!"
|
30
|
+
end
|
31
|
+
if (topic.length + data.length) > 250
|
32
|
+
raise ArgumentError, "Message packet length exceeded!"
|
33
|
+
end
|
34
|
+
|
35
|
+
x_logd("Sending '#{topic}': '#{data}'")
|
36
|
+
|
37
|
+
@mqtt.publish_to @mqtt_topic + "Send/#{topic}", data
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
|
2
|
+
require_relative 'Base.rb'
|
3
|
+
|
4
|
+
require 'serialport'
|
5
|
+
require 'xasin_logger'
|
6
|
+
|
7
|
+
module TEF
|
8
|
+
module FurComs
|
9
|
+
class Serial < Base
|
10
|
+
include XasLogger::Mix
|
11
|
+
|
12
|
+
def initialize(port)
|
13
|
+
super();
|
14
|
+
|
15
|
+
@port = SerialPort.new(port);
|
16
|
+
@port.baud = 115200;
|
17
|
+
@port.sync = true;
|
18
|
+
|
19
|
+
start_thread();
|
20
|
+
|
21
|
+
init_x_log("FurComs #{port}")
|
22
|
+
x_logi("Ready!");
|
23
|
+
end
|
24
|
+
|
25
|
+
private def decode_data_string(data)
|
26
|
+
return if(data.length() < 9)
|
27
|
+
payload = data[8..-1]
|
28
|
+
topic, _sep, payload = payload.partition("\0")
|
29
|
+
|
30
|
+
# Filter out unsafe topics
|
31
|
+
return unless topic =~ /^[\w\s\/]*$/
|
32
|
+
|
33
|
+
handout_data(topic, payload);
|
34
|
+
end
|
35
|
+
|
36
|
+
private def start_thread()
|
37
|
+
@rx_thread = Thread.new() do
|
38
|
+
had_esc = false;
|
39
|
+
rx_buffer = '';
|
40
|
+
c = 0;
|
41
|
+
|
42
|
+
loop do
|
43
|
+
c = @port.getbyte
|
44
|
+
if c == 0
|
45
|
+
decode_data_string rx_buffer
|
46
|
+
rx_buffer = ''
|
47
|
+
elsif had_esc
|
48
|
+
case c
|
49
|
+
when 0xDC
|
50
|
+
rx_buffer += "\0"
|
51
|
+
when 0xDD
|
52
|
+
rx_buffer += "\xDB"
|
53
|
+
end
|
54
|
+
had_esc = false
|
55
|
+
elsif c == 0xDB
|
56
|
+
had_esc = true
|
57
|
+
else
|
58
|
+
rx_buffer += c.chr
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
@rx_thread.abort_on_exception = true
|
64
|
+
end
|
65
|
+
|
66
|
+
private def slip_encode_data(data_str)
|
67
|
+
data_str.bytes.map do |b|
|
68
|
+
if b == 0
|
69
|
+
[0xDB, 0xDC]
|
70
|
+
elsif b == 0xDB
|
71
|
+
[0xDB, 0xDD]
|
72
|
+
else
|
73
|
+
b
|
74
|
+
end
|
75
|
+
end.flatten
|
76
|
+
end
|
77
|
+
|
78
|
+
private def generate_furcom_message(priority, chip_id, data_str)
|
79
|
+
priority = ([[-60, priority].max, 60].min + 64) * 2 + 1;
|
80
|
+
chip_id = 0x1 | 0x100 | ((chip_id & 0xEF) << 9) | ((chip_id >> 6) & 0xEF);
|
81
|
+
|
82
|
+
out_data = [0x00, priority, chip_id, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF]
|
83
|
+
out_data += data_str + [0]
|
84
|
+
|
85
|
+
out_data
|
86
|
+
end
|
87
|
+
|
88
|
+
def send_message(topic, message, priority: 0, chip_id: 0)
|
89
|
+
unless topic =~ /^[\w\s\/]*$/
|
90
|
+
raise ArgumentError, "Topic includes invalid characters!"
|
91
|
+
end
|
92
|
+
if (topic.length + message.length) > 250
|
93
|
+
raise ArgumentError, "Message packet length exceeded!"
|
94
|
+
end
|
95
|
+
|
96
|
+
x_logd("Sending '#{topic}': '#{message}'")
|
97
|
+
|
98
|
+
escaped_str = slip_encode_data "#{topic}\0#{message}"
|
99
|
+
out_data = generate_furcom_message priority, chip_id, escaped_str;
|
100
|
+
|
101
|
+
@port.write(out_data.pack("C2S<C*"))
|
102
|
+
|
103
|
+
@port.flush
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
require_relative 'Serial.rb'
|
3
|
+
|
4
|
+
module TEF
|
5
|
+
module FurComs
|
6
|
+
class SerialToMQTT < Serial
|
7
|
+
def initialize(port, mqtt, topic = nil)
|
8
|
+
super(port);
|
9
|
+
|
10
|
+
@mqtt = mqtt;
|
11
|
+
@mqtt_topic = topic || "FurComs/#{port.sub('/dev/', '')}/";
|
12
|
+
|
13
|
+
@mqtt.subscribe_to @mqtt_topic + 'Send/#' do |data, topic|
|
14
|
+
topic = topic.join('/')
|
15
|
+
|
16
|
+
next if data.length + topic.length > 250
|
17
|
+
next unless topic =~ /^[\w\s\/]*$/
|
18
|
+
|
19
|
+
self.send_message topic, data
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def handout_data(topic, data)
|
24
|
+
super(topic, data);
|
25
|
+
|
26
|
+
@mqtt.publish_to @mqtt_topic + "Received/#{topic}", data
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/tef/furcoms.rb
ADDED
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tef-furcoms
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- TheSystem
|
8
|
+
- Xasin
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2020-05-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: serialport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.3'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.3'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: xasin-logger
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0.1'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0.1'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: mqtt-sub_handler
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0.1'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0.1'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rubocop
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.77.0
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.77.0
|
70
|
+
description: Communication interfaces for TEF FurComs-compatible lines
|
71
|
+
email:
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- README.md
|
77
|
+
- lib/tef/furcoms.rb
|
78
|
+
- lib/tef/furcoms/Base.rb
|
79
|
+
- lib/tef/furcoms/MQTT.rb
|
80
|
+
- lib/tef/furcoms/Serial.rb
|
81
|
+
- lib/tef/furcoms/SerialToMQTT.rb
|
82
|
+
homepage:
|
83
|
+
licenses:
|
84
|
+
- GPL-3.0
|
85
|
+
metadata: {}
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 2.5.2.1
|
103
|
+
signing_key:
|
104
|
+
specification_version: 4
|
105
|
+
summary: Ruby-Gem for TheElectricFursuit FurComs
|
106
|
+
test_files: []
|