lego-boost.js 12 KB

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