oschii_ruby 0.0.1 → 0.0.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb0e8b35b66541a40236ea7a4595518d8a9d6727105c2543e74ca5d6fbb8443f
4
- data.tar.gz: 1d9c121b90502130c86056f9818dca4b6a81fe9485734e257e9f261891bbe6f8
3
+ metadata.gz: 578aa88e4dd107c6af19e80da3419deae8fbcc56052cb8272a824f81ceaaddd3
4
+ data.tar.gz: 9f3b0a12310effb1832975cd5edba9846e2a83550b2df0e8ee4554d6175414a2
5
5
  SHA512:
6
- metadata.gz: 8b35574e7713cdc5bf13d0e9710894818bc48c72a7a86ade3c6b8688a4449548a2106b01adeb52ac99585f7356f195b4c90999029a0b2aca3c1c6f3d170fb0c0
7
- data.tar.gz: 57a436a356063c353d9e8f5a5a18014fce3aa2016b689f50b7daef79cf3efcba1a643d6081fb5669a81e0ddcbb8230735575439e3d1db2dba915d8c13dadb106
6
+ metadata.gz: 6558856f498bc70b8fa419aa3bb65f43c1cecd66337a2c1bdd3e5b6e8bd3e49f042751f16280370f5f17ef53e4675d9c656e5a33d28423b3f5e2a0f0ee3c2a89
7
+ data.tar.gz: 1d28d3da39dc9de4326b577d1aa19780ac5d369952ba7274fb441544460714902801f8e3bfaf4fb45d85c24ddf350a9bb89e48877d466259c92128ace69c0bba
data/Gemfile CHANGED
@@ -9,4 +9,5 @@ gemspec
9
9
  group :development do
10
10
  gem 'make_menu'
11
11
  gem 'byebug'
12
+ gem 'bump'
12
13
  end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- oschii_ruby (0.0.1)
4
+ oschii_ruby (0.0.6)
5
5
  activesupport (~> 7.1.2)
6
6
  faye-websocket (~> 0.11.3)
7
7
  osc-ruby (~> 1.1.4)
@@ -24,6 +24,7 @@ GEM
24
24
  tzinfo (~> 2.0)
25
25
  base64 (0.2.0)
26
26
  bigdecimal (3.1.5)
27
+ bump (0.10.0)
27
28
  byebug (11.1.3)
28
29
  concurrent-ruby (1.2.2)
29
30
  connection_pool (2.4.1)
@@ -69,6 +70,7 @@ PLATFORMS
69
70
  arm64-darwin-21
70
71
 
71
72
  DEPENDENCIES
73
+ bump
72
74
  byebug
73
75
  make_menu
74
76
  oschii_ruby!
@@ -0,0 +1,48 @@
1
+ module Oschii
2
+ class Component
3
+ def initialize(type, config)
4
+ @type = type
5
+ @config = config
6
+ end
7
+
8
+ attr_reader :type, :config
9
+
10
+ def name
11
+ @name ||= config['name']
12
+ end
13
+
14
+ def array_name
15
+ @array_name ||= "#{type.capitalize}s"
16
+ end
17
+
18
+ def reference
19
+ "#{type}:#{name}"
20
+ end
21
+
22
+ def routes
23
+ @routes ||= config['routes'] || config['Routes'] || config['subs'] || config['Subs'] || []
24
+ end
25
+
26
+ def targets
27
+ return @targets if @targets
28
+
29
+ @targets = config['targets'] || config['target'] || config['~'] || []
30
+ @targets = [@targets] if @targets.is_a?(String)
31
+
32
+ routes.each do |route|
33
+ target_refs = route['targets'] || route['target'] || route['~'] || []
34
+ target_refs = [target_refs] if target_refs.is_a?(String)
35
+ @targets += target_refs
36
+ end
37
+ @targets.map { |ref| ref.split('/').first }.uniq
38
+ end
39
+
40
+ def to_s
41
+ inspect
42
+ end
43
+
44
+ def inspect
45
+ "#<#{self.class.name} '#{reference}'>"
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,183 @@
1
+ require_relative 'component'
2
+ require_relative 'template'
3
+ require 'json'
4
+
5
+ module Oschii
6
+ # LOGO = '
7
+ # ╔═╗┌─┐┌─┐┬ ┬┬┬
8
+ # ║ ║└─┐│ ├─┤││
9
+ # ╚═╝└─┘└─┘┴ ┴┴┴'
10
+
11
+ COMPONENT_TYPES = %w(Sensor Driver Reporter Listener Monitor State Timer Pixel I2C).freeze
12
+ I2C = 'I2C'.freeze
13
+ BASIC_COMPONENT_TYPES = COMPONENT_TYPES.reject { |t| t == I2C }.freeze
14
+
15
+ TemplateError = Class.new(StandardError)
16
+
17
+ class Config
18
+ def initialize(json)
19
+ @config = json.is_a?(String) ? JSON.parse(json) : json
20
+ @components = {}
21
+ @startups = []
22
+ @templates = load_templates
23
+ @sda = -1
24
+ @scl = -1
25
+ @clock = 100_000
26
+ @name = nil
27
+ @description = nil
28
+ build
29
+ end
30
+
31
+ def self.from_file(filename)
32
+ Config.new(File.read(filename))
33
+ end
34
+
35
+ attr_reader :components, :templates, :scl, :sda, :clock,
36
+ :name, :description, :config, :startups
37
+
38
+ def load_templates
39
+ Dir.glob("./templates/*.json").map do |filename|
40
+ conf = JSON.parse(File.read(filename))
41
+ template = Template.new(
42
+ conf, conf['name'] || filename.gsub('.json', '').split('/').last
43
+ )
44
+ [template.name, template]
45
+ end.to_h
46
+ end
47
+
48
+ def add_component(comp)
49
+ components[comp.reference] = comp
50
+ end
51
+
52
+ def build
53
+
54
+ @name = config['name']
55
+ @description = config['description']
56
+ @startups = config['Startups'] || []
57
+
58
+ puts inspect
59
+
60
+ BASIC_COMPONENT_TYPES.each do |type|
61
+ config["#{type}s"]&.each do |comp_def|
62
+ comp = Component.new(type, comp_def)
63
+ puts " + #{comp}"
64
+ add_component comp
65
+ end
66
+ end
67
+
68
+ if (i2c = config[I2C])
69
+ @sda = i2c['sdaPin'] || sda
70
+ @scl = i2c['sclPin'] || scl
71
+ @clock = i2c['clock'] || clock
72
+ i2c['modules']&.each do |comp_def|
73
+ comp = Component.new(I2C, comp_def)
74
+ puts " + #{comp}"
75
+ add_component comp
76
+ end
77
+ end
78
+
79
+ # Get templates defined within this config
80
+ config['Templates']&.each do |conf|
81
+ templates[conf['name']] = Template.new(conf)
82
+ end
83
+
84
+ config['Customs']&.each do |custom_def|
85
+ build_custom_component custom_def
86
+ end
87
+
88
+ build_missing_targets
89
+
90
+ self
91
+ end
92
+
93
+ def build_custom_component(custom_def, name_prefix = '', indent = 0)
94
+ template = templates[custom_def['template']]
95
+
96
+ raise TemplateError, "Custom:#{custom_def['name']} - Template '#{custom_def['template']}' not defined" unless template
97
+
98
+ puts "#{' ' * indent} Custom:#{template.name}:#{name_prefix}#{custom_def['name']}"
99
+
100
+ template.build_components(custom_def, name_prefix).each do |comp|
101
+ puts "#{' ' * (indent+1)} + #{comp}"
102
+ add_component comp
103
+ end
104
+
105
+ @startups += template.startups
106
+
107
+ template.embedded_customs&.each do |inner_custom_def|
108
+ build_custom_component inner_custom_def, "#{custom_def['name']}_", indent + 1
109
+ end
110
+ end
111
+
112
+ def build_missing_targets
113
+ missing_comps = []
114
+
115
+ components.each do |ref, comp|
116
+ comp.targets.each do |target_ref|
117
+ next unless components[target_ref].nil?
118
+
119
+ type, name = target_ref.split(':')
120
+ puts name
121
+ name = name.split('/').first
122
+ unless name.start_with?('*')
123
+ new_comp = Component.new(type, { 'name' => name, 'warning' => 'Auto-created by Oschii Parser' })
124
+ missing_comps << new_comp
125
+ end
126
+ end
127
+ end
128
+ unless missing_comps.empty?
129
+ puts
130
+ puts "WARNING: Creating empty components for unresolved target references."
131
+ puts " Output configuration may not be valid!"
132
+ puts
133
+
134
+ missing_comps.uniq do |comp|
135
+ next if components[comp.reference]
136
+
137
+ puts " + #{comp}"
138
+ add_component comp
139
+ end
140
+ end
141
+ end
142
+
143
+ def to_h
144
+ conf = {}
145
+
146
+ conf[:name] = @name if @name
147
+ conf[:description] = @description if @description
148
+
149
+ conf[:Startup] = startups
150
+
151
+ components.each do |_ref, comp|
152
+ if comp.type == I2C
153
+ conf[I2C] ||= {
154
+ sdaPin: sda, sclPin: scl, clock: clock, modules: []
155
+ }
156
+ conf[I2C][:modules] << comp.config
157
+ else
158
+ array = (conf[comp.array_name] ||= [])
159
+ array << comp.config
160
+ end
161
+ end
162
+ conf
163
+ end
164
+
165
+ def to_json
166
+ to_h.to_json
167
+ end
168
+
169
+ def to_pretty_json
170
+ JSON.pretty_generate to_h
171
+ end
172
+
173
+ def inspect
174
+ "#<#{self.class} '#{name}'>"
175
+ end
176
+
177
+ def to_s
178
+ components.collect do |_ref, comp|
179
+ "#{comp.type}:#{comp.name} => #{comp.config}"
180
+ end.join "\n"
181
+ end
182
+ end
183
+ end
data/lib/oschii/device.rb CHANGED
@@ -6,6 +6,7 @@ require 'faye/websocket'
6
6
  require 'eventmachine'
7
7
  require 'byebug'
8
8
 
9
+ require_relative 'config'
9
10
  module Oschii
10
11
  DeviceUnavailable = Class.new(StandardError)
11
12
  NoConnection = Class.new(StandardError)
@@ -145,7 +146,7 @@ module Oschii
145
146
  end
146
147
 
147
148
  def config
148
- @config ||= Oschii::Config.parse(raw_config)
149
+ @config ||= Oschii::Config.new(raw_config)
149
150
  end
150
151
 
151
152
  def clear!
@@ -0,0 +1,40 @@
1
+ require_relative 'config'
2
+
3
+ puts Oschii::LOGO
4
+ puts ' P A R S E R'
5
+ puts
6
+
7
+ if ARGV.empty?
8
+ puts 'Please specify an input file'
9
+ exit 0
10
+ end
11
+
12
+ input_filename = ARGV[0]
13
+ input_filename = "#{input_filename}.json" unless input_filename.end_with? '.json'
14
+
15
+ unless File.exists? input_filename
16
+ puts "File '#{input_filename}' not found"
17
+ exit 0
18
+ end
19
+
20
+ output_filename = ARGV[1] || "#{input_filename.gsub('.json', '')}_output.json"
21
+ output_filename = "#{output_filename}.json" unless output_filename.end_with? '.json'
22
+
23
+ begin
24
+ puts "Parsing '#{input_filename}'...."
25
+ puts
26
+ conf = Oschii::Config.from_file(input_filename)
27
+ rescue Oschii::TemplateError => e
28
+ puts
29
+ puts "ERROR! #{e.message}"
30
+ puts
31
+ exit 1
32
+ end
33
+
34
+ puts
35
+ puts "Writing '#{output_filename}'...."
36
+ puts
37
+ File.write(output_filename, conf.to_pretty_json)
38
+
39
+ puts 'OK'
40
+ puts
@@ -5,3 +5,15 @@ include Oschii
5
5
  if ENV['OSCHII_AUTO_POPULATE']
6
6
  populate
7
7
  end
8
+
9
+ if ENV['OSCHII_AUTO_LOOKUP']
10
+ def method_missing(m, *args, &block)
11
+ return if @cloud.nil?
12
+
13
+ node = cloud.get(m)
14
+
15
+ return node unless node.nil?
16
+
17
+ raise NameError
18
+ end
19
+ end
@@ -0,0 +1,96 @@
1
+ module Oschii
2
+ class Template
3
+ def initialize(config, name = nil)
4
+ @config = config
5
+ @name = name || config['name']
6
+ @params = {}
7
+ @embedded_customs = []
8
+ @startups = []
9
+ end
10
+
11
+ attr_reader :config, :name, :params, :embedded_customs, :startups
12
+
13
+ def fill_params(json)
14
+ string = json.to_json
15
+
16
+ params.each do |name, value|
17
+ case value
18
+ when Integer, Float, TrueClass, FalseClass
19
+ string.gsub! "\"${#{name}}\"", "#{value}"
20
+ else
21
+ string.gsub! "${#{name}}", "#{value}"
22
+ end
23
+ end
24
+
25
+ JSON.parse(string)
26
+ end
27
+
28
+ def build_components(custom_config, name_prefix = '')
29
+ bind_params custom_config
30
+
31
+ @embedded_customs = []
32
+
33
+ config["Customs"]&.each do |inner_custom_def|
34
+ @embedded_customs << fill_params(inner_custom_def)
35
+ end
36
+
37
+ BASIC_COMPONENT_TYPES.map do |type|
38
+ config["#{type}s"]&.map do |comp|
39
+ comp_conf = comp.dup
40
+
41
+ comp_conf['name'] = "#{name_prefix}#{custom_config['name']}_#{comp['name']}"
42
+
43
+ string = comp_conf.to_json
44
+
45
+ params.each do |name, value|
46
+ case value
47
+ when Integer, Float, TrueClass, FalseClass
48
+ string.gsub! "\"${#{name}}\"", "#{value}"
49
+ else
50
+ string.gsub! "${#{name}}", "#{value}"
51
+ end
52
+ end
53
+
54
+ # Expand in-Template Component References
55
+ string.gsub!(':@', ":#{name_prefix}#{custom_config['name']}_")
56
+
57
+ Component.new(type, JSON.parse(string))
58
+ end
59
+ end.flatten.compact
60
+ end
61
+
62
+ def param_names
63
+ config.to_s.scan(/\$\{\w+}/).collect do |tag|
64
+ tag.gsub('${', '').gsub('}', '')
65
+ end.uniq
66
+ end
67
+
68
+
69
+ def bind_params(custom_config)
70
+ missing_params = []
71
+ param_names.each do |param|
72
+ value = custom_config[param]
73
+ if value
74
+ params[param] = value
75
+ else
76
+ missing_params << param
77
+ end
78
+ end
79
+
80
+ unless missing_params.empty?
81
+ missing_params.each do |param|
82
+ puts "No value for '#{param}'"
83
+ end
84
+ raise Oschii::TemplateError, "Custom:#{custom_config['name']}: Missing parameters"
85
+ end
86
+ end
87
+
88
+ def to_s
89
+ inspect
90
+ end
91
+
92
+ def inspect
93
+ "#<#{self.class} '#{name}'>"
94
+ end
95
+ end
96
+ end
@@ -1,3 +1,3 @@
1
1
  module Oschii
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.6'
3
3
  end
data/lib/oschii.rb CHANGED
@@ -11,8 +11,7 @@ module Oschii
11
11
  ╔═╗┌─┐┌─┐┬ ┬┬┬
12
12
  ║ ║└─┐│ ├─┤││
13
13
  ╚═╝└─┘└─┘┴ ┴┴┴
14
- -- R U B Y ---
15
- #{VERSION.center(14)}
14
+ #{"ruby gem #{VERSION}".center(14)}
16
15
 
17
16
  ".freeze
18
17
 
@@ -40,16 +39,6 @@ module Oschii
40
39
  @serial ||= cloud.find_serial
41
40
  end
42
41
 
43
- def method_missing(m, *args, &block)
44
- return if @cloud.nil?
45
-
46
- node = cloud.get(m)
47
-
48
- return node unless node.nil?
49
-
50
- raise NameError
51
- end
52
-
53
42
  def send_osc(ip, address, *values, port: 3333)
54
43
  OSC::Client.new(ip, port).send(OSC::Message.new(address, *values.to_a))
55
44
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oschii_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Barri Mason
@@ -104,12 +104,16 @@ files:
104
104
  - Gemfile.lock
105
105
  - lib/oschii.rb
106
106
  - lib/oschii/cloud.rb
107
+ - lib/oschii/component.rb
108
+ - lib/oschii/config.rb
107
109
  - lib/oschii/device.rb
108
110
  - lib/oschii/http_device.rb
109
111
  - lib/oschii/osc_monitor.rb
112
+ - lib/oschii/parser.rb
110
113
  - lib/oschii/serial_device.rb
111
114
  - lib/oschii/servlets.rb
112
115
  - lib/oschii/session.rb
116
+ - lib/oschii/template.rb
113
117
  - lib/oschii/version.rb
114
118
  homepage: https://rubygems.org/gems/oschii_ruby
115
119
  licenses: