noolite.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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. return nil, errors.New(d.LastError())
  77. }
  78. d.Interface(0)
  79. if d.LastError() != "No error" {
  80. return nil, errors.New(d.LastError())
  81. }
  82. return &NooliteAdapter{d, m}, nil
  83. }
  84. // Return NooliteAdapter object with default work mode values:
  85. //
  86. // work mode: 0
  87. // bitrate: 2 (for 1000 bit/sec)
  88. // command repeats: 2
  89. func DefaultNooliteAdapter() (*NooliteAdapter, error) { // Default constructor
  90. return NewNooliteAdapter(0, 2, 2)
  91. }
  92. func (n *NooliteAdapter) composeCommand(cmd command, channel int, args ...int) []byte {
  93. c := make([]byte, 8)
  94. c[0] = n.mode
  95. c[1] = byte(cmd)
  96. c[4] = byte(channel)
  97. if cmd == set {
  98. l := len(args)
  99. switch l {
  100. case 1:
  101. {
  102. c[2] = 0x01
  103. c[5] = byte(args[0])
  104. }
  105. case 3:
  106. {
  107. c[2] = 0x03
  108. for i, v := range args {
  109. c[5+i] = byte(v)
  110. }
  111. }
  112. default:
  113. panic("Bad arguments for SET command")
  114. }
  115. }
  116. return c
  117. }
  118. func (n *NooliteAdapter) sendCommand(command []byte) error {
  119. n.ControlMsg(0x21, 0x09, 0x300, 0, command)
  120. if n.LastError() != "No error" {
  121. return errors.New(n.LastError())
  122. }
  123. return nil
  124. }
  125. // Turn power OFF for specified channel
  126. func (n *NooliteAdapter) Off(channel int) error {
  127. cmd := n.composeCommand(off, channel)
  128. return n.sendCommand(cmd)
  129. }
  130. // Smooth brightnes decrase for specified channel
  131. func (n *NooliteAdapter) DecraseBrightnes(channel int) error {
  132. cmd := n.composeCommand(decBrightnes, channel)
  133. return n.sendCommand(cmd)
  134. }
  135. // Turn power ON for specified channel
  136. func (n *NooliteAdapter) On(channel int) error {
  137. cmd := n.composeCommand(on, channel)
  138. return n.sendCommand(cmd)
  139. }
  140. // Smooth brightnes incrase for specified channel
  141. func (n *NooliteAdapter) IncraseBrightnes(channel int) error {
  142. cmd := n.composeCommand(incBrightnes, channel)
  143. return n.sendCommand(cmd)
  144. }
  145. // Switch power state between off and on for specified channel
  146. func (n *NooliteAdapter) Switch(channel int) error {
  147. cmd := n.composeCommand(cSwitch, channel)
  148. return n.sendCommand(cmd)
  149. }
  150. // Smooth brightnes incrase or decrase for specified channel
  151. func (n *NooliteAdapter) InvertBrightnes(channel int) error {
  152. cmd := n.composeCommand(invertBrightnes, channel)
  153. return n.sendCommand(cmd)
  154. }
  155. // Set brightnes value for specified channel
  156. //
  157. // Value must be in range 35..155.
  158. // When value == 0 lights off.
  159. // When value > 155 lights on for full brightness.
  160. func (n *NooliteAdapter) SetBrightnesValue(channel, value int) error {
  161. cmd := n.composeCommand(set, channel, value)
  162. return n.sendCommand(cmd)
  163. }
  164. // Set brightnes values for independens channels
  165. //
  166. // Available for SD111-180 only
  167. func (n *NooliteAdapter) SetBrightnesValues(channel, val1, val2, val3 int) error {
  168. cmd := n.composeCommand(set, channel, val1, val2, val3)
  169. return n.sendCommand(cmd)
  170. }
  171. // Call scenario for specified channel
  172. func (n *NooliteAdapter) CallScenario(channel int) error {
  173. cmd := n.composeCommand(callScenario, channel)
  174. return n.sendCommand(cmd)
  175. }
  176. // Save scenario for specified channel
  177. func (n *NooliteAdapter) SaveScenario(channel int) error {
  178. cmd := n.composeCommand(saveScenario, channel)
  179. return n.sendCommand(cmd)
  180. }
  181. // Unbind signal for specified channel
  182. func (n *NooliteAdapter) UnbindChannel(channel int) error {
  183. cmd := n.composeCommand(unbind, channel)
  184. return n.sendCommand(cmd)
  185. }
  186. // Stop color selection for specified channel
  187. //
  188. // Available for SD111-180 only
  189. func (n *NooliteAdapter) StopColorSelection(channel int) error {
  190. cmd := n.composeCommand(stopColorSelection, channel)
  191. return n.sendCommand(cmd)
  192. }
  193. // Set binding for specified channel
  194. func (n *NooliteAdapter) BindChannel(channel int) error {
  195. cmd := n.composeCommand(bind, channel)
  196. return n.sendCommand(cmd)
  197. }
  198. // Smooth color changing for specified channel
  199. //
  200. // Stop with StopColorSelection method
  201. //
  202. // Avialable for SD111-180 only
  203. func (n *NooliteAdapter) ColorSelection(channel int) error {
  204. cmd := n.composeCommand(colorSelection, channel)
  205. return n.sendCommand(cmd)
  206. }
  207. // Switch color for specified channel
  208. //
  209. // Avialable for SD111-180 only
  210. func (n *NooliteAdapter) ColorSwitch(channel int) error {
  211. cmd := n.composeCommand(colorSwitch, channel)
  212. return n.sendCommand(cmd)
  213. }
  214. // Switch work mode for specified channel
  215. //
  216. // Avialable for SD111-180 only
  217. func (n *NooliteAdapter) ModeSwitch(channel int) error {
  218. cmd := n.composeCommand(modeSwitch, channel)
  219. return n.sendCommand(cmd)
  220. }
  221. // Set change color speed for specified channel
  222. //
  223. // Avialable for SD111-180 only
  224. func (n *NooliteAdapter) EffectSpeed(channel int) error {
  225. cmd := n.composeCommand(effectSpeed, channel)
  226. return n.sendCommand(cmd)
  227. }