alphasign 0.2.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +5 -1
- data/Rakefile +8 -5
- data/VERSION +1 -1
- data/alphasign.gemspec +9 -5
- data/examples/alphaclock.rb +39 -0
- data/lib/alphasign.rb +89 -36
- data/lib/alphasign/format.rb +3 -1
- data/lib/alphasign/protocol.rb +19 -0
- data/test/test_alphasign.rb +29 -17
- metadata +12 -8
data/CHANGELOG
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
* 0.
|
1
|
+
* 0.3.0
|
2
|
+
Implement fixed set of memory files
|
3
|
+
Implement string file write and call
|
4
|
+
Add examples/alphaclock.rb usage example
|
5
|
+
* 0.2.0
|
2
6
|
write method now takes STRING and HASH of options (this is
|
3
7
|
incompatible with older positional args)
|
4
8
|
move constants into modules
|
data/Rakefile
CHANGED
@@ -19,11 +19,14 @@ Jeweler::Tasks.new do |gem|
|
|
19
19
|
gem.license = "MIT"
|
20
20
|
gem.summary = "A gem for communicating with LED signs using Alpha Sign Protocol "
|
21
21
|
gem.description = <<-EOF
|
22
|
-
Alphasign is handles communication with LED signs using the
|
23
|
-
These include Alpha signs
|
24
|
-
others too, YMMV.
|
25
|
-
|
26
|
-
|
22
|
+
Alphasign is handles communication with LED signs using the
|
23
|
+
Alpha Sign Protocol. These include Alpha signs and Betabrite signs
|
24
|
+
by Adaptive Micro Systems, maybe others too, YMMV.
|
25
|
+
|
26
|
+
This release handles writing "text files" and "string" files to the
|
27
|
+
sign over rs232 serial port, using a fixed memory configuration. Upcoming
|
28
|
+
releases will add "dots picture" files and memory user accesable memory
|
29
|
+
file configuration.
|
27
30
|
EOF
|
28
31
|
gem.email = "jon@jonproulx.com"
|
29
32
|
gem.authors = ["Jon Proulx"]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.1
|
data/alphasign.gemspec
CHANGED
@@ -5,16 +5,19 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{alphasign}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.1"
|
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
12
|
s.date = %q{2012-03-10}
|
13
|
-
s.description = %q{Alphasign is handles communication with LED signs using the
|
14
|
-
These include Alpha signs
|
15
|
-
others too, YMMV.
|
13
|
+
s.description = %q{Alphasign is handles communication with LED signs using the
|
14
|
+
Alpha Sign Protocol. These include Alpha signs and Betabrite signs
|
15
|
+
by Adaptive Micro Systems, maybe others too, YMMV.
|
16
16
|
|
17
|
-
|
17
|
+
This release handles writing "text files" and "string" files to the
|
18
|
+
sign over rs232 serial port, using a fixed memory configuration. Upcoming
|
19
|
+
releases will add "dots picture" files and memory user accesable memory
|
20
|
+
file configuration.
|
18
21
|
}
|
19
22
|
s.email = %q{jon@jonproulx.com}
|
20
23
|
s.extra_rdoc_files = [
|
@@ -31,6 +34,7 @@ Initial release only handles writing text to the sign over rs232 serial port.
|
|
31
34
|
"Rakefile",
|
32
35
|
"VERSION",
|
33
36
|
"alphasign.gemspec",
|
37
|
+
"examples/alphaclock.rb",
|
34
38
|
"lib/alphasign.rb",
|
35
39
|
"lib/alphasign/format.rb",
|
36
40
|
"lib/alphasign/protocol.rb",
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This program display a clock on your alpha sign
|
4
|
+
#
|
5
|
+
# It uses a "String" file to hold the formatted time. String files
|
6
|
+
# use buffered writes so the display doesn't blank like it does when
|
7
|
+
# writing "text" files, but they are limited to 125 bytes each max
|
8
|
+
#
|
9
|
+
# File types need to be set in memory before they can used, both their
|
10
|
+
# type and size. For simplicity we use the default memory setup
|
11
|
+
# provided by AlphaSign.new :default is a text file of 256 bytes max
|
12
|
+
# and :str2 is a string file of 80 bytes max
|
13
|
+
require 'rubygems'
|
14
|
+
require 'alphasign'
|
15
|
+
|
16
|
+
# use second of the two default string files
|
17
|
+
stringfile=:str2
|
18
|
+
sign=AlphaSign.new
|
19
|
+
#seconds to sleep before refresh (signs can only handle updates every
|
20
|
+
#2 sec or so)
|
21
|
+
interval=5
|
22
|
+
|
23
|
+
# write our message to the default text file
|
24
|
+
#
|
25
|
+
# setting color, fixed text, and call our variable string file
|
26
|
+
sign.write(AlphaSign::Color[:amber] +
|
27
|
+
"the time is " + sign.callstr(stringfile))
|
28
|
+
|
29
|
+
#update stringfile every interval seconds
|
30
|
+
while 1
|
31
|
+
time = Time.new
|
32
|
+
# put time in our stringfile
|
33
|
+
# use fixed width so line doesn't squirm around when digits change
|
34
|
+
# this does force left justification rather than center
|
35
|
+
# set color, then write time
|
36
|
+
sign.writestr(AlphaSign::FixWidth + AlphaSign::Color[:green] +
|
37
|
+
time.strftime("%I:%M:%S %p"),stringfile)
|
38
|
+
sleep interval - time.sec.modulo(interval)
|
39
|
+
end
|
data/lib/alphasign.rb
CHANGED
@@ -12,55 +12,108 @@ class AlphaSign
|
|
12
12
|
# @param [String] device the serial device the sign is connected to
|
13
13
|
# for now we only speak rs232
|
14
14
|
def initialize (device = "/dev/ttyS0")
|
15
|
-
@device=
|
15
|
+
@device=SerialPort.new(device, Baud, DataBits, StopBits, Parity)
|
16
|
+
@memsync=false
|
17
|
+
# default file setup, we should read this from the device, for now
|
18
|
+
# just enforce our own & hope no other process is messing with it
|
19
|
+
# (that's why we're 0.x.x)
|
20
|
+
@files={
|
21
|
+
# 256 byte text file always displayed
|
22
|
+
:default => AlphaFile.new(:txt, "A", "0100", "FF00"),
|
23
|
+
# 80 byte string file
|
24
|
+
:str1 => AlphaFile.new(:str, "B", "0050", "0000"),
|
25
|
+
# another string file
|
26
|
+
:str2 => AlphaFile.new(:str, "C", "0050", "0000"),
|
27
|
+
# 16 (0x10) row by 120 (0x78) column dots file in 3 colors
|
28
|
+
# not sure why but htat's what "2000" means in this context
|
29
|
+
:dot1 => AlphaFile.new(:dot, "D", "1078", "2000"),
|
30
|
+
# another dots file
|
31
|
+
:dot2 => AlphaFile.new(:dot, "E", "1078", "2000"),
|
32
|
+
}
|
16
33
|
|
17
34
|
# Protocol allows multiple signs on the same port, we are not
|
18
35
|
# going to expose that possibility yet but we will recognize this
|
19
|
-
# as an instance variable Where "Z" all
|
20
|
-
|
21
|
-
|
22
|
-
|
36
|
+
# as an instance variable Where "Z" all unit types, "00" is broadcast
|
37
|
+
@addr = 'Z00'
|
38
|
+
|
39
|
+
# write out initial memory config to sign
|
40
|
+
writemem
|
23
41
|
end
|
24
42
|
|
25
|
-
#
|
26
|
-
#
|
27
|
-
# @
|
28
|
-
# for control characters for color, font, etc.
|
43
|
+
# This is for writing "txt" files
|
44
|
+
# @param [STRING] msg the message (text file in Alpha parlance)
|
45
|
+
# @see AlphaSign::Format for control characters for color, font, etc.
|
29
46
|
# @param [HASH] opts the write options
|
30
47
|
# @option opts [Symbol] :position display position @see AlphaSign::Format::Position
|
31
48
|
# @options opts [Symbol] :mode display mode @see AlphaSign::Format::Mode
|
32
|
-
# @options opts [
|
33
|
-
# or nil (for comand modes that don't use it) any value from 0x20
|
34
|
-
# to 0x75 except 0x30 which is reserved
|
49
|
+
# @options opts [Symbol] :filename a key from @files hash for a configured :txt file
|
35
50
|
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
51
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
else
|
46
|
-
@filelabel=[opts[:fileLabel]].pack("C")
|
47
|
-
end
|
52
|
+
# default to middle position
|
53
|
+
opts[:position]=:middle unless opts[:position]
|
54
|
+
|
55
|
+
#default to static display
|
56
|
+
opts[:mode]=:hold unless opts[:mode]
|
48
57
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
58
|
+
# sign file to write to, carefule these need to be setup before
|
59
|
+
# they can be written to...
|
60
|
+
opts[:filename]=:default unless opts [:filename]
|
61
|
+
raise ArgumentError.new(":filename must be a preconfigured as a txt file in momory")unless @files[opts[:filename]].type == :txt
|
62
|
+
|
63
|
+
@format = StartMode + Position[opts[:position]] + Mode[opts[:mode]]
|
64
|
+
|
65
|
+
rawwrite StartCMD[:wtxt]+ @files[opts[:filename]].label + @format + msg
|
57
66
|
end
|
67
|
+
|
68
|
+
# write to a string file (this must then be called from a text file
|
69
|
+
# for display, but string files are buffered so good for frequent
|
70
|
+
# updates without flashing screen like txt files do
|
71
|
+
# @param [STRING] msg the message string
|
72
|
+
# @see AlphaSign::Format for control characters for color, font, etc.
|
73
|
+
# @param [Symbol] filename a key from @files hash for a configure :txt file
|
74
|
+
# defaults to ":str1" part of default memory config
|
75
|
+
|
76
|
+
def writestr (msg,filename=:str1)
|
77
|
+
raise ArgumentError.new("filename must be a preconfigured as a string file in momory")unless @files[filename].type == :str
|
78
|
+
rawwrite StartCMD[:wstr] + @files[filename].label + msg
|
79
|
+
end
|
58
80
|
|
59
|
-
#
|
81
|
+
# this returns code to insert a named string file in txt file
|
82
|
+
def callstr (filename=:str1)
|
83
|
+
raise ArgumentError.new("filename must be a preconfigured as a string file in momory")unless @files[filename].type == :str
|
84
|
+
CallString + @files[filename].label
|
85
|
+
end
|
86
|
+
|
87
|
+
# write a memory config. This is all at once can't add files even if
|
88
|
+
# there's unassigned memory, so what ever is written overwrites
|
89
|
+
# previous config
|
90
|
+
private
|
91
|
+
def writemem
|
92
|
+
#reset memorystring
|
93
|
+
@memorystring=StartCMD[:wfctn]+"$" # "$" is the memory function
|
94
|
+
locked="U"
|
95
|
+
# rebuld memory string from our current files hash damn this is
|
96
|
+
# ugly maybe I do want files to be a Class not a Struct...
|
97
|
+
@files.keys.each do |file|
|
98
|
+
if @files[file].type == :str
|
99
|
+
locked="L"
|
100
|
+
else
|
101
|
+
locked="U"
|
102
|
+
end
|
103
|
+
@memorystring=@memorystring +
|
104
|
+
@files[file].label +
|
105
|
+
FileType[@files[file].type] + locked +
|
106
|
+
@files[file].size_spec + @files[file].time_spec
|
107
|
+
end
|
108
|
+
rawwrite @memorystring
|
109
|
+
@memsync=true
|
110
|
+
end
|
111
|
+
|
112
|
+
# the most generic write function
|
113
|
+
private
|
60
114
|
def rawwrite (msg)
|
61
|
-
|
62
|
-
Baud, DataBits, StopBits, Parity)
|
63
|
-
sp.write msg
|
64
|
-
sp.close
|
115
|
+
@device.write StartHeader + @addr + msg + Footer
|
65
116
|
end
|
117
|
+
|
118
|
+
|
66
119
|
end
|
data/lib/alphasign/format.rb
CHANGED
@@ -89,13 +89,15 @@ module AlphaSign::Format
|
|
89
89
|
[0x18].pack("C"), [0x19].pack("C") ]
|
90
90
|
|
91
91
|
#Control Codes (for insertion in text file data)
|
92
|
+
CallString = [0x10].pack("C") # call a saved string file, must be followed but filelabel for a string file...
|
93
|
+
CallDots = [0x14].pack("C") # call a saved Dots Picture file, must be followed but filelabel for a dots file...
|
92
94
|
DoubleHighOn = [0x05,0x31].pack("C2") # not supported on all units
|
93
95
|
DoubleHighOff= [0x05,0x30].pack("C2") # default
|
94
96
|
TrueDecendersOn = [0x06,0x31].pack("C2") # not supported on all units
|
95
97
|
TrueDecendersOff= [0x06,0x30].pack("C2") # default
|
96
98
|
FlashCharOn = [0x07,0x31].pack("C2") # not supported on all units
|
97
99
|
FlashCharOff= [0x07,0x30].pack("C2") # default
|
98
|
-
|
100
|
+
FixWidth=[0x1E,0x31].pack("C2") # set fixed width useful for string files
|
99
101
|
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
102
|
|
101
103
|
TempF=[0x08,0x1C].pack("C2") #only available on incandescent message centers
|
data/lib/alphasign/protocol.rb
CHANGED
@@ -30,6 +30,25 @@ module AlphaSign::Protocol
|
|
30
30
|
:radots => [ 0x02, 'N' ].pack('CA'), # read ALPHAVISON DOTS picture file
|
31
31
|
:bulletin => [ 0x02, 'O' ].pack('CA'), # write bulletin message
|
32
32
|
}
|
33
|
+
|
34
|
+
# FileType is used in allocating sign memory
|
35
|
+
FileType = {
|
36
|
+
:txt => "A", # Text file
|
37
|
+
:str => "B", # String file
|
38
|
+
:dot => "D", # Dots picture file
|
39
|
+
}
|
40
|
+
|
41
|
+
# @param [Synmbol] type file type must be a key of
|
42
|
+
# AlphaSign::Protocol::FileType
|
43
|
+
# @param [String] label, file label to assign 0x20 to 0x75 (0x30 is
|
44
|
+
# reserver for "priority text file"
|
45
|
+
# @param [String] file size, 4 char uppercase ASCII hex
|
46
|
+
# representation
|
47
|
+
# @param [String] time spec, 4 char uppercase ASCII hex
|
48
|
+
# representation. First two char represent start time code, second
|
49
|
+
# two end time code "FF00" == always, see docs for full spec, it's
|
50
|
+
# wierd...
|
51
|
+
AlphaFile=Struct.new(:type,:label,:size_spec,:time_spec)
|
33
52
|
|
34
53
|
Footer = [0x04].pack("C") # EOT end of transmission
|
35
54
|
|
data/test/test_alphasign.rb
CHANGED
@@ -2,37 +2,49 @@ require 'helper'
|
|
2
2
|
|
3
3
|
class TestAlphasign < Test::Unit::TestCase
|
4
4
|
def setup
|
5
|
+
# this test *will* fail if you don't have serialport on /dev/ttyS0
|
5
6
|
@sign=AlphaSign.new()
|
6
|
-
@notsign=AlphaSign.new('/dev/null')
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_simple_write
|
10
|
-
|
11
|
-
exception=assert_raise(ArgumentError) {
|
10
|
+
assert_nothing_raised { @sign.write("foo" ) }
|
11
|
+
exception=assert_raise(ArgumentError) {
|
12
|
+
@notsign=AlphaSign.new('/dev/null')
|
13
|
+
}
|
12
14
|
assert_equal("not a serial port",exception.message)
|
13
15
|
end
|
14
16
|
|
15
17
|
def test_write_modes
|
16
|
-
|
17
|
-
|
18
|
+
assert_nothing_raised do
|
19
|
+
AlphaSign::Mode.keys.each do |mode|
|
20
|
+
@sign.write("foo", :mode => mode.to_sym)
|
21
|
+
end
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
21
25
|
def test_write_positions
|
22
|
-
|
23
|
-
|
26
|
+
assert_nothing_raised do
|
27
|
+
AlphaSign::Position.keys.each do |pos|
|
28
|
+
@sign.write("foo", :position => pos.to_sym)
|
29
|
+
end
|
24
30
|
end
|
25
31
|
end
|
26
32
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
assert_raise(ArgumentError)
|
33
|
+
def test_sting_files
|
34
|
+
assert_nothing_raised do
|
35
|
+
@sign.writestr("foo")
|
36
|
+
@sign.writestr("foo",:str1)
|
37
|
+
@sign.writestr("foo",:str2)
|
38
|
+
@sign.callstr
|
39
|
+
@sign.callstr(:str1)
|
40
|
+
@sign.callstr(:str2)
|
41
|
+
end
|
42
|
+
assert_raise(ArgumentError) do
|
43
|
+
@sign.writestr("foo",:default)
|
44
|
+
@sign.writestr("foo",:nonesuch)
|
45
|
+
@sign.callstr(:default)
|
46
|
+
@sign.callstr(:nonesuch)
|
47
|
+
end
|
37
48
|
end
|
38
49
|
end
|
50
|
+
|
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:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 3
|
9
|
+
- 1
|
10
|
+
version: 0.3.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jon Proulx
|
@@ -109,11 +109,14 @@ dependencies:
|
|
109
109
|
version: "0"
|
110
110
|
requirement: *id006
|
111
111
|
description: |
|
112
|
-
Alphasign is handles communication with LED signs using the
|
113
|
-
These include Alpha signs
|
114
|
-
others too, YMMV.
|
112
|
+
Alphasign is handles communication with LED signs using the
|
113
|
+
Alpha Sign Protocol. These include Alpha signs and Betabrite signs
|
114
|
+
by Adaptive Micro Systems, maybe others too, YMMV.
|
115
115
|
|
116
|
-
|
116
|
+
This release handles writing "text files" and "string" files to the
|
117
|
+
sign over rs232 serial port, using a fixed memory configuration. Upcoming
|
118
|
+
releases will add "dots picture" files and memory user accesable memory
|
119
|
+
file configuration.
|
117
120
|
|
118
121
|
email: jon@jonproulx.com
|
119
122
|
executables: []
|
@@ -133,6 +136,7 @@ files:
|
|
133
136
|
- Rakefile
|
134
137
|
- VERSION
|
135
138
|
- alphasign.gemspec
|
139
|
+
- examples/alphaclock.rb
|
136
140
|
- lib/alphasign.rb
|
137
141
|
- lib/alphasign/format.rb
|
138
142
|
- lib/alphasign/protocol.rb
|