noolite.go 6.0 KB

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