lego-boost.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /*
  2. The MIT License (MIT)
  3. Copyright (c) 2014-2020 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
  4. */
  5. // VWF & Lego Boost driver
  6. import {Fabric} from '/core/vwf/fabric.js';
  7. class LegoBoostView extends Fabric {
  8. constructor(module) {
  9. console.log("LegoBoostView constructor");
  10. super(module, 'View');
  11. }
  12. factory() {
  13. let _self_ = this;
  14. return this.load(this.module,
  15. {
  16. initialize: function () {
  17. let self = this;
  18. this.fabric = _self_;
  19. //this.lego = LegoBoost;
  20. //window._osc = this.osc;
  21. window._LegoView = this;
  22. this.boost = window._LegoBoost;
  23. this.device = {
  24. id: _app.helpers.randId(),
  25. info: {}
  26. }
  27. this.initStream();
  28. },
  29. firedEvent: function (nodeID, eventName, eventParameters) {
  30. let self = this;
  31. if (eventName == 'done') {
  32. var clientThatSatProperty = self.kernel.client();
  33. var me = self.kernel.moniker();
  34. // If the transform property was initially updated by this view....
  35. if (clientThatSatProperty == me) {
  36. //do on event
  37. }
  38. }
  39. },
  40. satProperty: function (nodeId, propertyName, propertyValue) {
  41. },
  42. /*
  43. * Receives incoming messages
  44. */
  45. calledMethod: function (nodeID, methodName, methodParameters, methodValue) {
  46. let self = this;
  47. let isLegoBoost = _self_.checkLegoID(nodeID);
  48. let isLegoBoostClone = _self_.checkLegoCloneID(nodeID);
  49. if (self.boost && self.isConnected()) {
  50. //if (nodeID.includes(self.device.id)) {
  51. if (isLegoBoost || isLegoBoostClone) {
  52. if (methodName == "getDeviceInfo") {
  53. self.device.info = _self_.getDeviceInfo();
  54. //sendToAllViews(self.device.info);
  55. let key = methodParameters[0];
  56. self.kernel.callMethod(nodeID, "gotDeviceInfo", [self.device.info, key]);
  57. }
  58. if (methodName == "setDelay") {
  59. let delayTime = methodParameters[0];
  60. let promiseAction =
  61. async function () {
  62. return new Promise((resolve, reject) => {
  63. setTimeout(function () {
  64. resolve(delayTime)
  65. }, delayTime)
  66. }).then(r => {
  67. return {
  68. check: {
  69. isLegoBoost: isLegoBoost,
  70. isLegoBoostClone: isLegoBoostClone
  71. },
  72. methodName: methodName,
  73. action: "lego",
  74. nodeID: nodeID,
  75. methodParameters: [r]
  76. }
  77. })
  78. }
  79. self.streamAdapter.induce(promiseAction);
  80. }
  81. if (methodName == "setLed") {
  82. //Possible string values: `off`, `pink`, `purple`, `blue`, `lightblue`, `cyan`, `green`, `yellow`, `orange`, `red`, `white`
  83. let ledColor = methodParameters[0];
  84. let promiseAction = async function () {
  85. return self.boost.ledAsync(ledColor).then(r => {
  86. return {
  87. check: {
  88. isLegoBoost: isLegoBoost,
  89. isLegoBoostClone: isLegoBoostClone
  90. },
  91. action: "lego",
  92. nodeID: nodeID,
  93. methodName: methodName,
  94. methodParameters: [ledColor],
  95. res: r
  96. }
  97. })
  98. }
  99. self.streamAdapter.induce(promiseAction);
  100. }
  101. if (methodName == "setMotorAngle") {
  102. //port, angle, dutyCycle, wait
  103. let port = methodParameters[0];
  104. let angle = Math.abs(methodParameters[1]);
  105. let dutyCycle = methodParameters[2];
  106. let promiseAction = async function () {
  107. return self.boost.motorAngleAsync(port, angle, dutyCycle).then(r => {
  108. return {
  109. check: {
  110. isLegoBoost: isLegoBoost,
  111. isLegoBoostClone: isLegoBoostClone
  112. },
  113. action: "lego",
  114. nodeID: nodeID,
  115. methodName: methodName,
  116. methodParameters: [port, angle, dutyCycle],
  117. res: r
  118. }
  119. })
  120. }
  121. self.streamAdapter.induce(promiseAction);
  122. }
  123. } else {
  124. //It's another Lego boost connected, false by default - ASYNC operations, if true - SEQUENTIAL
  125. if (methodName == "sat_setMotorAngle" || methodName == "sat_setLed" || methodName == "sat_setDelay") {
  126. if (self.waitPromise) {
  127. self.waitPromise.resolve(
  128. {
  129. action: "wait"
  130. }
  131. )
  132. }
  133. }
  134. if (methodName == "setMotorAngle" || methodName == "setLed" || methodName == "setDelay") {
  135. if (methodParameters[1] == 'sync' || methodParameters[3] == 'sync') {
  136. let promiseAction =
  137. async function () {
  138. var _resolve, _reject;
  139. self.waitPromise = new Promise((resolve, reject) => {
  140. _resolve = resolve;
  141. _reject = reject;
  142. })
  143. self.waitPromise.resolve = _resolve;
  144. self.waitPromise.reject = _reject;
  145. return self.waitPromise
  146. }
  147. self.streamAdapter.induce(promiseAction);
  148. }
  149. }
  150. }
  151. }
  152. },
  153. // ticked: function (vwfTime) {
  154. // if (self.boost){
  155. // if (self.boost.deviceInfo.connected){
  156. // let legoBoostNode = self.device.id;
  157. // self.kernel.callMethod(legoBoostNode, "gotDeviceInfo", [self.device.info]);
  158. // }
  159. // }
  160. // },
  161. connect: function () {
  162. //connect
  163. console.log('connect Lego boost!');
  164. this.boost.connect();
  165. },
  166. disconnect: function () {
  167. console.log('disconnect Lego boost!');
  168. this.boost.disconnect();
  169. //
  170. },
  171. testLED: function () {
  172. //connect
  173. console.log('test Lego Boost');
  174. this.boost.changeLed();
  175. },
  176. isConnected: function () {
  177. return this.boost.deviceInfo.connected
  178. },
  179. changeDeviceID: function (id) {
  180. this.device.id = id
  181. },
  182. initStream: function () {
  183. let self = this;
  184. console.log("Init stream of promises!");
  185. self.streamScheduler = M.scheduler.newDefaultScheduler();
  186. const [induce, events] = M.createAdapter();
  187. self.streamAdapter = {
  188. induce: induce,
  189. events: events
  190. }
  191. const tapFunction = function (res) {
  192. if (res && res.action == "lego") {
  193. //call sat_ only on master lego (not clones if exist)
  194. if (res.check.isLegoBoost) {
  195. self.kernel.callMethod(res.nodeID, "sat_" + res.methodName, res.methodParameters)
  196. }
  197. }
  198. console.log(res);
  199. }
  200. const result = M.concatMap((x) => M.fromPromise(x()), events);
  201. self.eventsStream = M.tap(res => { tapFunction(res) }, result); //mostCore.awaitPromises(events)
  202. M.runEffects(self.eventsStream, self.streamScheduler);
  203. }
  204. })
  205. }
  206. getDeviceInfo() {
  207. let self = this.instance;
  208. let deviceInfo = {
  209. led: self.boost.color,
  210. color: self.boost.deviceInfo.color,
  211. connected: self.boost.deviceInfo.connected,
  212. distance: self.boost.deviceInfo.distance,
  213. error: self.boost.deviceInfo.error,
  214. rssi: self.boost.deviceInfo.rssi,
  215. tilt: self.boost.deviceInfo.tilt,
  216. ports: {
  217. A: {
  218. action: self.boost.deviceInfo.ports.A.action,
  219. angle: self.boost.deviceInfo.ports.A.angle,
  220. },
  221. B: {
  222. action: self.boost.deviceInfo.ports.B.action,
  223. angle: self.boost.deviceInfo.ports.B.angle,
  224. },
  225. AB: {
  226. action: self.boost.deviceInfo.ports.AB.action,
  227. angle: self.boost.deviceInfo.ports.AB.angle,
  228. },
  229. C: {
  230. action: self.boost.deviceInfo.ports.C.action,
  231. angle: self.boost.deviceInfo.ports.C.angle,
  232. },
  233. D: {
  234. action: self.boost.deviceInfo.ports.D.action,
  235. angle: self.boost.deviceInfo.ports.D.angle,
  236. },
  237. LED: {
  238. action: self.boost.deviceInfo.ports.LED.action,
  239. angle: self.boost.deviceInfo.ports.LED.angle,
  240. }
  241. }
  242. }
  243. return deviceInfo
  244. }
  245. checkLegoID(nodeID) {
  246. let self = this.instance;
  247. let prop = vwf.getProperty(nodeID, 'boostID');
  248. if (prop !== undefined) {
  249. return (prop == self.device.id) ? true : false
  250. }
  251. return false
  252. }
  253. checkLegoCloneID(nodeID) {
  254. let self = this.instance;
  255. let prop = vwf.getProperty(nodeID, 'boostID');
  256. if (prop !== undefined) {
  257. return (prop.includes(self.device.id + '_clone')) ? true : false
  258. }
  259. return false
  260. }
  261. }
  262. export { LegoBoostView as default }