alphasign 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+
2
+ Major props to Walt wls@wls.wwco.com for hunting down and hosting the ALpha
3
+ Signs protocol documentation at
4
+ http://wls.wwco.com/ledsigns/alpha/led97088061.html
5
+
6
+ Thanks also got to Sean Reifschneider who's python code I started
7
+ hacking from ftp://ftp.tummy.com/pub/tummy/betabritelinux/ though
8
+ almost none of that is left so all tahnks to him all blame to me...
@@ -0,0 +1,16 @@
1
+ * 0.2.0 (pre)
2
+ write method now takes STRING and HASH of options (this is
3
+ incompatible with older positional args)
4
+ move constants into modules
5
+ add many formatting constants
6
+ expose rawwrite method for testing (this will not stay)
7
+ improve code coments
8
+ add Acknowledgements
9
+ add link to protocol spec in README
10
+ * 0.1.2
11
+ fix StartCMD by splitting out file label which is different and variable
12
+ add some formatting constants
13
+ * 0.1.1
14
+ add trivial example code to README
15
+ * 0.1.0
16
+ write textfile to sign over rs232 works
@@ -17,7 +17,8 @@ to work.
17
17
 
18
18
 
19
19
  == Contributing to alphasign
20
-
20
+
21
+ * Protocol specification can be found at http://wls.wwco.com/ledsigns/alpha/led97088061.html (complete with sample code in BASIC), this is a good place to start reading
21
22
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
22
23
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
23
24
  * Fork the project.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{alphasign}
8
- s.version = "0.1.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jon Proulx"]
12
- s.date = %q{2012-03-05}
12
+ s.date = %q{2012-03-10}
13
13
  s.description = %q{Alphasign is handles communication with LED signs using the Alpha Sign Protocol.
14
14
  These include Alpha signs and Betabrite signs by Adaptive Micro Systems, maybe
15
15
  others too, YMMV.
@@ -23,6 +23,8 @@ Initial release only handles writing text to the sign over rs232 serial port.
23
23
  ]
24
24
  s.files = [
25
25
  ".document",
26
+ "ACKNOWLEDGEMENTS",
27
+ "CHANGELOG",
26
28
  "Gemfile",
27
29
  "LICENSE.txt",
28
30
  "README.rdoc",
@@ -30,6 +32,8 @@ Initial release only handles writing text to the sign over rs232 serial port.
30
32
  "VERSION",
31
33
  "alphasign.gemspec",
32
34
  "lib/alphasign.rb",
35
+ "lib/alphasign/format.rb",
36
+ "lib/alphasign/protocol.rb",
33
37
  "test/helper.rb",
34
38
  "test/test_alphasign.rb"
35
39
  ]
@@ -1,93 +1,13 @@
1
1
  class AlphaSign
2
2
  # Require 'serialport' gem
3
3
  require 'serialport'
4
-
5
- #We have a relatively large number of potocol constants
6
4
 
7
- ###Serial config
8
- Baud=9600
9
- DataBits=7
10
- Parity=SerialPort::EVEN
11
- StopBits=2
12
- ###
5
+ #We have a relatively large number of potocol and formatting constants
6
+ require 'alphasign/protocol'
7
+ require 'alphasign/format'
8
+ include AlphaSign::Protocol
9
+ include AlphaSign::Format
13
10
 
14
- #this was much more complex in original, but due to packing spec
15
- #effectively reduced to this, and remains voodoo but apparently
16
- #necessary voodoo
17
- Preamble = [ ']', ']'].pack('x10ax10a')
18
- # everything starts with this, nulls are to auto set baud on unit
19
- StartHeader = Preamble + [ 0x01 ].pack('x20C')
20
- # only handlers for :wtxt implemented so far
21
- StartCMD = {
22
- :wtxt => [ 0x02, 'A' ].pack('CA'), # write text file
23
- :rtxt => [ 0x02, 'B' ].pack('CA'), # read text file
24
- :wfctn => [ 0x02, 'E' ].pack('CA'), # write special function
25
- :rfctn => [ 0x02, 'F' ].pack('CA'), # read special function
26
- :wstr => [ 0x02, 'G' ].pack('CA'), # write string file
27
- :rstr => [ 0x02, 'H' ].pack('CA'), # read string file
28
- :wdots => [ 0x02, 'I' ].pack('CA'), # write DOTS picture file
29
- :rdots => [ 0x02, 'J' ].pack('CA'), # read DOTS picture file
30
- :wadots => [ 0x02, 'M' ].pack('CA'), # write ALPHAVISON DOTS picture file
31
- :radots => [ 0x02, 'N' ].pack('CA'), # read ALPHAVISON DOTS picture file
32
- :bulletin => [ 0x02, 'O' ].pack('CA'), # write bulletin message
33
- }
34
-
35
- # Marker for start of mode config
36
- StartMode = [ 0x1b ].pack('C')
37
-
38
- # Vertical Position
39
- Position = {
40
- :middle => [ 0x20 ].pack('C'),
41
- :top => [ 0x22 ].pack('C'),
42
- :bottom => [ 0x26 ].pack('C'),
43
- :fill => [ 0x30 ].pack('C'),
44
- }
45
- # Mode Code, names taken form documentation
46
- # since these are ascii probably don't need packing?
47
- Mode = {
48
- :rotate => ["a"].pack('A'), #scroll right to left
49
- :hold => ["b"].pack('A'), # stationary
50
- :flash => ["c"].pack('A'), #"flash"
51
- # these are all transitions from previous message:
52
- :rollup => ["e"].pack('A'),
53
- :rolldown => ["f"].pack('A'),
54
- :rollleft => ["g"].pack('A'),
55
- :rollright => ["h"].pack('A'),
56
- :wipeup => ["i"].pack('A'),
57
- :wipedown => ["j"].pack('A'),
58
- }
59
-
60
- Footer = [0x04].pack("C") # EOT end of transmission
61
-
62
- # standard color codes, limited by hardware
63
- Color = {
64
- :red => [0x1c,0x31].pack("C2"),
65
- :green => [0x1c,0x32].pack("C2"),
66
- :amber => [0x1c,0x33].pack("C2"),
67
- :dimred => [0x1c,0x34].pack("C2"),
68
- :dimgreen => [0x1c,0x35].pack("C2"),
69
- :brown => [0x1c,0x36].pack("C2"),
70
- :orange => [0x1c,0x37].pack("C2"),
71
- :yellow => [0x1c,0x38].pack("C2"),
72
- :rainbow1 => [0x1c,0x39].pack("C2"),
73
- :rainbow2 => [0x1c,0x41].pack("C2"),
74
- :mix => [0x1c,0x42].pack("C2"),
75
- :auto => [0x1c,0x43].pack("C2"),
76
- }
77
-
78
- # Character sets height & style
79
- CharSet = {
80
- :std5 => [0x1a,0x31].pack("C2"),
81
- :std7 => [0x1a,0x33].pack("C2"),
82
- :fancy7 => [0x1a,0x35].pack("C2"),
83
- :std10 => [0x1a,0x36].pack("C2"),
84
- :fullfancy => [0x1a,0x38].pack("C2"),
85
- :fullstd => [0x1a,0x39].pack("C2"),
86
- }
87
-
88
- # speeds from slow to fast
89
- Speed = [ [0x15].pack("C"), [0x16].pack("C"), [0x17].pack("C"),
90
- [0x18].pack("C"), [0x19].pack("C") ]
91
11
 
92
12
  # @param [String] device the serial device the sign is connected to
93
13
  # for now we only speak rs232
@@ -103,14 +23,31 @@ class AlphaSign
103
23
  end
104
24
 
105
25
  # we don't have an open yet so this still kludgey and enfoces using
106
- # only :wtxt command as thats the only one we know we can do
107
- def write (msg, position=:middle, mode=:hold)
108
- @fileLabel = [ 0x41 ].pack("C") # any value from 0x20 to 0x75
109
- # except 0x30 which is reserved
110
- # for "Priority Text" file
111
- # according to docs
112
- @alphaFormat = StartMode + Position[position] + Mode[mode]
113
- @alphaHeader = StartHeader + @addr + StartCMD[:wtxt] + @fileLabel + @alphaFormat
26
+ # only :wtxt command as thats the only one we know we can do @param
27
+ # @param [STRING] msg the message (text file in Alpha parlance) @see AlphaSign::Format
28
+ # for control characters for color, font, etc.
29
+ # @param [HASH] opts the write options
30
+ # @option opts [Symbol] :position display position @see AlphaSign::Format::Position
31
+ # @options opts [Symbol] :mode display mode @see AlphaSign::Format::Mode
32
+ # @options opts [Integer] or [Nil] :fileLabel file label to write to
33
+ # or nil (for comand modes that don't use it) any value from 0x20
34
+ # to 0x75 except 0x30 which is reserved
35
+ def write (msg, opts={ })
36
+ opts[:position]=:middle unless opts[:position] # default to middle position
37
+ opts[:mode]=:hold unless opts[:mode] #default to static display
38
+ opts[:fileLabel] = 0x41 unless opts[:fileLabel] #this was default in exampelso why not..
39
+
40
+ raise ArgumentError.new("unkown position #{opts[:position]}") unless Position.has_key?(opts[:position])
41
+ raise ArgumentError.new("unkown mode #{opts[:mode]}") unless Mode.has_key?(opts[:mode])
42
+ raise ArgumentError.new("invalid File Label specification") unless (opts[:fileLabel] == nil) or ((opts[:fileLabel].kind_of? Integer) and ( opts[:fileLabel] >= 0x20 and opts[:fileLabel] <= 0x75 and opts[:fileLabel] != 0x30))
43
+ if opts[:fileLabel] == nil
44
+ @filelabel=""
45
+ else
46
+ @filelabel=[opts[:fileLabel]].pack("C")
47
+ end
48
+
49
+ @alphaFormat = StartMode + Position[opts[:position]] + Mode[opts[:mode]]
50
+ @alphaHeader = StartHeader + @addr + StartCMD[:wtxt] + @filelabel + @alphaFormat
114
51
  sp=SerialPort.new(@device,
115
52
  Baud, DataBits, StopBits, Parity)
116
53
  sp.write @alphaHeader
@@ -119,6 +56,11 @@ class AlphaSign
119
56
  sp.close
120
57
  end
121
58
 
122
-
123
-
59
+ #raw serial port for testing this will go away (or atleast become private)
60
+ def rawwrite (msg)
61
+ sp=SerialPort.new(@device,
62
+ Baud, DataBits, StopBits, Parity)
63
+ sp.write msg
64
+ sp.close
65
+ end
124
66
  end
@@ -0,0 +1,110 @@
1
+ # Constants for format codes users may want to include
2
+ # @see AlphaSign::Protocol for protocol constants
3
+ module AlphaSign::Format
4
+ # Marker for start of mode config
5
+ StartMode = [ 0x1b ].pack('C')
6
+ # Vertical Position
7
+ Position = {
8
+ :middle => [ 0x20 ].pack('C'),
9
+ :top => [ 0x22 ].pack('C'),
10
+ :bottom => [ 0x26 ].pack('C'),
11
+ :fill => [ 0x30 ].pack('C'),
12
+ }
13
+ # Mode Code, names taken form documentation
14
+ Mode = {
15
+ :rotate => "a", #scroll right to left
16
+ :hold => "b", # stationary
17
+ :flash => "c", #"flash"
18
+ # these are all transitions from previous message:
19
+ :rollup => "e",
20
+ :rolldown => "f",
21
+ :rollleft => "g",
22
+ :rollright => "h",
23
+ :wipeup => "i",
24
+ :wipedown => "j",
25
+ :wipeleft => "k",
26
+ :wiperight => "l",
27
+ :scroll => "m", # push bottom line to top (2line units only)
28
+ :auto => "o",
29
+ :rollin => "p",
30
+ :rollout => "q",
31
+ :wipein => "r",
32
+ :wipeout => "s",
33
+ :compressed_rotate => "t",
34
+ # only certain (unspecified) models
35
+ # special modes, note these are ascii "n" and ascii digits so "1"
36
+ # is 0x31 not not 0x01
37
+ :twinkle => "n0",
38
+ :sparkle => "n1",
39
+ :snow => "n2",
40
+ :interlock => "n3",
41
+ :switch => "n4",
42
+ :slide => "n5",
43
+ :spray => "n6",
44
+ :starburst => "n7",
45
+ # @note special graphics are not display modes, though they are in
46
+ # the same manual seciton and transmision frame placement. If
47
+ # ASCII message data is to b edisplayed following a special
48
+ # graphic, another mode field is required other wise the message
49
+ # will appear in "automode"
50
+ :script_welcome => "n8",
51
+ :slot_machine => "n9",
52
+ :script_thx => "nS",
53
+ :no_smoking => "nU",
54
+ :dont_drink_drive => "nV",
55
+ :running_animal => "nW",
56
+ :fireworks => "nX",
57
+ :turbo_car => "nY",
58
+ :cherry_bomb => "nZ",
59
+ }
60
+
61
+ # standard color codes, limited by hardware
62
+ Color = {
63
+ :red => [0x1c,0x31].pack("C2"),
64
+ :green => [0x1c,0x32].pack("C2"),
65
+ :amber => [0x1c,0x33].pack("C2"),
66
+ :dimred => [0x1c,0x34].pack("C2"),
67
+ :dimgreen => [0x1c,0x35].pack("C2"),
68
+ :brown => [0x1c,0x36].pack("C2"),
69
+ :orange => [0x1c,0x37].pack("C2"),
70
+ :yellow => [0x1c,0x38].pack("C2"),
71
+ :rainbow1 => [0x1c,0x39].pack("C2"),
72
+ :rainbow2 => [0x1c,0x41].pack("C2"),
73
+ :mix => [0x1c,0x42].pack("C2"),
74
+ :auto => [0x1c,0x43].pack("C2"),
75
+ }
76
+
77
+ # Character sets height & style
78
+ CharSet = {
79
+ :std5 => [0x1a,0x31].pack("C2"),
80
+ :std7 => [0x1a,0x33].pack("C2"),
81
+ :fancy7 => [0x1a,0x35].pack("C2"),
82
+ :std10 => [0x1a,0x36].pack("C2"),
83
+ :fullfancy => [0x1a,0x38].pack("C2"),
84
+ :fullstd => [0x1a,0x39].pack("C2"),
85
+ }
86
+
87
+ # speeds from slow to fast
88
+ Speed = [ [0x15].pack("C"), [0x16].pack("C"), [0x17].pack("C"),
89
+ [0x18].pack("C"), [0x19].pack("C") ]
90
+
91
+ #Control Codes (for insertion in text file data)
92
+ DoubleHighOn = [0x05,0x31].pack("C2") # not supported on all units
93
+ DoubleHighOff= [0x05,0x30].pack("C2") # default
94
+ TrueDecendersOn = [0x06,0x31].pack("C2") # not supported on all units
95
+ TrueDecendersOff= [0x06,0x30].pack("C2") # default
96
+ FlashCharOn = [0x07,0x31].pack("C2") # not supported on all units
97
+ FlashCharOff= [0x07,0x30].pack("C2") # default
98
+
99
+ Extended=[0x08].pack("C") # access extended ascci of following char for example Extended + "I" would put a degree symbol on the display, see docs
100
+
101
+ TempF=[0x08,0x1C].pack("C2") #only available on incandescent message centers
102
+ TempC=[0x08,0x1D].pack("C2") #only available on incandescent message centers
103
+ Count1=[0x08,0x7A].pack("C2") #display current value of counter 1
104
+ Count2=[0x08,0x7B].pack("C2") #display current value of counter 2
105
+ Count3=[0x08,0x7C].pack("C2") #display current value of counter 3
106
+ Count4=[0x08,0x7D].pack("C2") #display current value of counter 4
107
+ Count5=[0x08,0x7E].pack("C2") #display current value of counter 5
108
+
109
+
110
+ end
@@ -0,0 +1,36 @@
1
+ # These are a pile of constants for the protocol functions
2
+ # @see AlphaSign::Format for constants users may want to interact with
3
+ module AlphaSign::Protocol
4
+
5
+ ###Serial config
6
+ Baud=9600
7
+ DataBits=7
8
+ Parity=SerialPort::EVEN
9
+ StopBits=2
10
+ ###
11
+
12
+ #this was much more complex in original, but due to packing spec
13
+ #effectively reduced to this, and remains voodoo but apparently
14
+ #necessary voodoo
15
+ Preamble = [ ']', ']'].pack('x10ax10a')
16
+ # everything starts with this, nulls are to auto set baud on unit
17
+ StartHeader = Preamble + [ 0x01 ].pack('x20C')
18
+
19
+ # only handlers for :wtxt implemented so far
20
+ StartCMD = {
21
+ :wtxt => [ 0x02, 'A' ].pack('CA'), # write text file
22
+ :rtxt => [ 0x02, 'B' ].pack('CA'), # read text file
23
+ :wfctn => [ 0x02, 'E' ].pack('CA'), # write special function
24
+ :rfctn => [ 0x02, 'F' ].pack('CA'), # read special function
25
+ :wstr => [ 0x02, 'G' ].pack('CA'), # write string file
26
+ :rstr => [ 0x02, 'H' ].pack('CA'), # read string file
27
+ :wdots => [ 0x02, 'I' ].pack('CA'), # write DOTS picture file
28
+ :rdots => [ 0x02, 'J' ].pack('CA'), # read DOTS picture file
29
+ :wadots => [ 0x02, 'M' ].pack('CA'), # write ALPHAVISON DOTS picture file
30
+ :radots => [ 0x02, 'N' ].pack('CA'), # read ALPHAVISON DOTS picture file
31
+ :bulletin => [ 0x02, 'O' ].pack('CA'), # write bulletin message
32
+ }
33
+
34
+ Footer = [0x04].pack("C") # EOT end of transmission
35
+
36
+ end
@@ -1,7 +1,38 @@
1
1
  require 'helper'
2
2
 
3
3
  class TestAlphasign < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
4
+ def setup
5
+ @sign=AlphaSign.new()
6
+ @notsign=AlphaSign.new('/dev/null')
7
+ end
8
+
9
+ def test_simple_write
10
+ assert_nil( @sign.write("foo" )) # this test *will* fail if you don't have serialport on /dev/ttyS0
11
+ exception=assert_raise(ArgumentError) { @notsign.write("foo" ) }
12
+ assert_equal("not a serial port",exception.message)
13
+ end
14
+
15
+ def test_write_modes
16
+ AlphaSign::Mode.keys.each do |mode|
17
+ assert_nil(@sign.write("foo", :mode => mode.to_sym))
18
+ end
19
+ end
20
+
21
+ def test_write_positions
22
+ AlphaSign::Position.keys.each do |pos|
23
+ assert_nil(@sign.write("foo", :position => pos.to_sym))
24
+ end
25
+ end
26
+
27
+ def test_write_to_file_label
28
+ assert_nil(@sign.write("foo", :fileLabel=>nil))
29
+ assert_nil(@sign.write("foo", :fileLabel=>0x20))
30
+ assert_nil(@sign.write("foo", :fileLabel=>0x29))
31
+ assert_nil(@sign.write("foo", :fileLabel=>0x31))
32
+ assert_nil(@sign.write("foo", :fileLabel=>0x75))
33
+ assert_raise(ArgumentError) {@sign.write("foo", :fileLabel=>"foo")}
34
+ assert_raise(ArgumentError) {@sign.write("foo", :fileLabel=>0x19)}
35
+ assert_raise(ArgumentError) {@sign.write("foo", :fileLabel=>0x30)}
36
+ assert_raise(ArgumentError) {@sign.write("foo", :fileLabel=>0x76)}
6
37
  end
7
38
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alphasign
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
8
  - 2
10
- version: 0.1.2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jon Proulx
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-03-05 00:00:00 -05:00
18
+ date: 2012-03-10 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -125,6 +125,8 @@ extra_rdoc_files:
125
125
  - README.rdoc
126
126
  files:
127
127
  - .document
128
+ - ACKNOWLEDGEMENTS
129
+ - CHANGELOG
128
130
  - Gemfile
129
131
  - LICENSE.txt
130
132
  - README.rdoc
@@ -132,6 +134,8 @@ files:
132
134
  - VERSION
133
135
  - alphasign.gemspec
134
136
  - lib/alphasign.rb
137
+ - lib/alphasign/format.rb
138
+ - lib/alphasign/protocol.rb
135
139
  - test/helper.rb
136
140
  - test/test_alphasign.rb
137
141
  has_rdoc: true