noolite.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. Copyright 2016 Denis V. Dedkov (denis.v.dedkov@gmail.com)
  3. This file is part of Noolite Go bindings.
  4. Noolite Go bindings is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. Noolite Go bindings is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with Noolite Go bindings. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. // Package noolite provide class for control Noolite Adapters PC11xx.
  16. // Protocol described on url:
  17. // http://www.noo.com.by/assets/files/software/PC11xx_HID_API.pdf
  18. package noolite
  19. import (
  20. "errors"
  21. "github.com/tonymagro/usb"
  22. )
  23. const (
  24. VID = 5824 // Vendor ID
  25. PID = 1503 // Product ID
  26. )
  27. // Available commands
  28. type command byte
  29. const (
  30. off command = iota
  31. decBrightnes
  32. on
  33. incBrightnes
  34. cSwitch
  35. invertBrightnes
  36. set
  37. callScenario
  38. saveScenario
  39. unbind
  40. stopColorSelection
  41. bind = iota + 0x04
  42. // Commands for SD111-180 only
  43. colorSelection
  44. colorSwitch
  45. modeSwitch
  46. effectSpeed
  47. )
  48. // Noolite Adapter class as USB HID
  49. type NooliteAdapter struct {
  50. *usb.Device
  51. mode byte
  52. }
  53. // Return NooliteAdapter object.
  54. //
  55. // work mode: range 0..7
  56. // bitrate: range 0..3
  57. // command repeats: range 0..7
  58. func NewNooliteAdapter(mode, bitrate, repeats uint) (*NooliteAdapter, error) {
  59. usb.Init()
  60. d := usb.Open(VID, PID)
  61. if d == nil {
  62. return nil, errors.New("Device not found")
  63. }
  64. if mode > 7 {
  65. return nil, errors.New("Mode must be in 0..7 range")
  66. }
  67. if bitrate > 3 {
  68. return nil, errors.New("Bitrate must be in 0..3 range")
  69. }
  70. if repeats > 7 {
  71. return nil, errors.New("Repeats must be in 0..7 range")
  72. }
  73. m := (byte(repeats) << 5) | (byte(bitrate) << 3) | byte(mode)
  74. d.Configuration(1)
  75. if d.LastError() != "No error" {
  76. d.Close()
  77. return nil, errors.New(d.LastError())
  78. }
  79. d.Interface(0)
  80. if d.LastError() != "No error" {
  81. d.Close()
  82. return nil, errors.New(d.LastError())
  83. }
  84. return &NooliteAdapter{d, m}, nil
  85. }
  86. // Return NooliteAdapter object with default work mode values:
  87. //
  88. // work mode: 0
  89. // bitrate: 2 (for 1000 bit/sec)
  90. // command repeats: 2
  91. func DefaultNooliteAdapter() (*NooliteAdapter, error) { // Default constructor
  92. return NewNooliteAdapter(0, 2, 2)
  93. }
  94. func (n *NooliteAdapter) composeCommand(cmd command, channel int, args ...int) []byte {
  95. c := make([]byte, 8)
  96. c[0] = n.mode
  97. c[1] = byte(cmd)
  98. c[4] = byte(channel)
  99. if cmd == set {
  100. l := len(args)
  101. switch l {
  102. case 1:
  103. {
  104. c[2] = 0x01
  105. c[5] = byte(args[0])
  106. }
  107. case 3:
  108. {
  109. c[2] = 0x03
  110. for i, v := range args {
  111. c[5+i] = byte(v)
  112. }
  113. }
  114. default:
  115. panic("Bad arguments for SET command")
  116. }
  117. }
  118. return c
  119. }
  120. func (n *NooliteAdapter) sendCommand(command []byte) error {
  121. n.ControlMsg(0x21, 0x09, 0x300, 0, command)
  122. if n.LastError() != "No error" {
  123. return errors.New(n.LastError())
  124. }
  125. return nil
  126. }
  127. // Turn power OFF for specified channel
  128. func (n *NooliteAdapter) Off(channel int) error {
  129. cmd := n.composeCommand(off, channel)
  130. return n.sendCommand(cmd)
  131. }
  132. // Smooth brightnes decrase for specified channel
  133. func (n *NooliteAdapter) DecraseBrightnes(channel int) error {
  134. cmd := n.composeCommand(decBrightnes, channel)
  135. return n.sendCommand(cmd)
  136. }
  137. // Turn power ON for specified channel
  138. func (n *NooliteAdapter) On(channel int) error {
  139. cmd := n.composeCommand(on, channel)
  140. return n.sendCommand(cmd)
  141. }
  142. // Smooth brightnes incrase for specified channel
  143. func (n *NooliteAdapter) IncraseBrightnes(channel int) error {
  144. cmd := n.composeCommand(incBrightnes, channel)
  145. return n.sendCommand(cmd)
  146. }
  147. // Switch power state between off and on for specified channel
  148. func (n *NooliteAdapter) Switch(channel int) error {
  149. cmd := n.composeCommand(cSwitch, channel)
  150. return n.sendCommand(cmd)
  151. }
  152. // Smooth brightnes incrase or decrase for specified channel
  153. func (n *NooliteAdapter) InvertBrightnes(channel int) error {
  154. cmd := n.composeCommand(invertBrightnes, channel)
  155. return n.sendCommand(cmd)
  156. }
  157. // Set brightnes value for specified channel
  158. //
  159. // Value must be in range 35..155.
  160. // When value == 0 lights off.
  161. // When value > 155 lights on for full brightness.
  162. func (n *NooliteAdapter) SetBrightnesValue(channel, value int) error {
  163. cmd := n.composeCommand(set, channel, value)
  164. return n.sendCommand(cmd)
  165. }
  166. // Set brightnes values for independens channels
  167. //
  168. // Available for SD111-180 only
  169. func (n *NooliteAdapter) SetBrightnesValues(channel, val1, val2, val3 int) error {
  170. cmd := n.composeCommand(set, channel, val1, val2, val3)
  171. return n.sendCommand(cmd)
  172. }
  173. // Call scenario for specified channel
  174. func (n *NooliteAdapter) CallScenario(channel int) error {
  175. cmd := n.composeCommand(callScenario, channel)
  176. return n.sendCommand(cmd)
  177. }
  178. // Save scenario for specified channel
  179. func (n *NooliteAdapter) SaveScenario(channel int) error {
  180. cmd := n.composeCommand(saveScenario, channel)
  181. return n.sendCommand(cmd)
  182. }
  183. // Unbind signal for specified channel
  184. func (n *NooliteAdapter) UnbindChannel(channel int) error {
  185. cmd := n.composeCommand(unbind, channel)
  186. return n.sendCommand(cmd)
  187. }
  188. // Stop color selection for specified channel
  189. //
  190. // Available for SD111-180 only
  191. func (n *NooliteAdapter) StopColorSelection(channel int) error {
  192. cmd := n.composeCommand(stopColorSelection, channel)
  193. return n.sendCommand(cmd)
  194. }
  195. // Set binding for specified channel
  196. func (n *NooliteAdapter) BindChannel(channel int) error {
  197. cmd := n.composeCommand(bind, channel)
  198. return n.sendCommand(cmd)
  199. }
  200. // Smooth color changing for specified channel
  201. //
  202. // Stop with StopColorSelection method
  203. //
  204. // Avialable for SD111-180 only
  205. func (n *NooliteAdapter) ColorSelection(channel int) error {
  206. cmd := n.composeCommand(colorSelection, channel)
  207. return n.sendCommand(cmd)
  208. }
  209. // Switch color for specified channel
  210. //
  211. // Avialable for SD111-180 only
  212. func (n *NooliteAdapter) ColorSwitch(channel int) error {
  213. cmd := n.composeCommand(colorSwitch, channel)
  214. return n.sendCommand(cmd)
  215. }
  216. // Switch work mode for specified channel
  217. //
  218. // Avialable for SD111-180 only
  219. func (n *NooliteAdapter) ModeSwitch(channel int) error {
  220. cmd := n.composeCommand(modeSwitch, channel)
  221. return n.sendCommand(cmd)
  222. }
  223. // Set change color speed for specified channel
  224. //
  225. // Avialable for SD111-180 only
  226. func (n *NooliteAdapter) EffectSpeed(channel int) error {
  227. cmd := n.composeCommand(effectSpeed, channel)
  228. return n.sendCommand(cmd)
  229. }