uniquejava / blog

My notes regarding the vibrating frontend :boom and the plain old java :rofl.
Creative Commons Zero v1.0 Universal
11 stars 5 forks source link

NativeScript/Vue.js/CoreMotion/MQTT/mosquitto #233

Open uniquejava opened 6 years ago

uniquejava commented 6 years ago

将手机自带传感器的motion/acceleration数据通过mqtt发到macbook上的local mqtt broker 终于跑通了, 先备份一下, 晚点再整理. screenshot 2018-07-31_23-43-59

nativescript-mqtt库有bug, 还好是开源的, 定位到错误

JavaScript error: file:///app/tns_modules/nativescript-mqtt/mqttws31.js:2058:72: JS ERROR Error: Invalid argument:object

修改了nativescript-mqtt/index.js中的publish方法: 修改前:

MQTTClient.prototype.publish = function (message) {
    this.mqttClient.send(message);
};

修改后

  MQTTClient.prototype.publish = function(message) {
    const { topic, payload, qos } = message;
    this.mqttClient.send(topic, payload, qos, false);
  };

最终是这么安装的

tns plugin remove nativescript-mqtt
tns plugin add https://github.com/uniquejava/nativescript-mqtt.git
tns run ios

主要的命令

DEVELOPMENT_TEAM = M5J7K9HVYA; # dist/app/App_Resources/iOS/build.xcconfig

vue init nativescript-vue/vue-cli-template hellons
cd 
npm i
npm i nativescript-coremotion
npm i nativescript-websockets #(碰到了这个问题https://github.com/NathanaelA/nativescript-websockets/issues/42)
npm i nativescript-mqtt
npm run clean
npm run watch:ios

主要的Home.vue

<template>
  <Page class="page">
    <ActionBar class="action-bar" title="Retail Display" />

    <StackLayout>
      <Button class="btn btn-primary" @tap="connectMqttBroker">Connect MQTT</Button>
      <Button class="btn btn-primary" @tap="$router.push('/counter')">Counter</Button>
      <Button class="btn btn-primary" @tap="$router.push('/hello')">Hello World</Button>
    </StackLayout>

  </Page>
</template>
<script>
import Coremotion from "nativescript-coremotion";
import { MQTTClient, ClientOptions } from "nativescript-mqtt";
import { Message } from "nativescript-mqtt/common";
let started = false;

export default {
  name: "home",
  methods: {
    data() {
      return {
        client: null,
        connected: false,
        mqtt_topic:
          "iot-2/type/sensor/id/myapp/evt/accelerometer_motion/fmt/json"
      };
    },
    connectMqttBroker() {
      console.log("connecting ...");

      let clientOptions = {
        host: "192.168.31.118",
        port: 9001,
        useSSL: false,
        path: "/mqtt"
      };

      let client = (this.client = new MQTTClient(clientOptions));

      client.connect("", "");

      client.onConnectionFailure.on(err => {
        console.log("Connection failed: " + JSON.stringify(err));
        this.connected = false;
      });

      client.onConnectionSuccess.on(() => {
        console.log("Connected successfully!");
        this.connected = true;
        this.subscribe();
      });

      client.onConnectionLost.on(err => {
        this.connected = false;
        console.log("Connection lost: " + JSON.stringify(err));
      });
    },

    subscribe() {
      //this.client.subscribe(this.mqtt_topic);
    }
  },
  mounted() {
    const topic =
      "iot-2/type/sensor/id/myapp/evt/accelerometer_motion/fmt/json";
    if (!started) {
      started = true;

      let available = Coremotion.isAccelerometerAvailable();
      console.log("Coremotion.isAccelerometerAvailable()=", available);
      if (available) {
        Coremotion.setAccelerometerUpdateInterval(2);
        Coremotion.startAccelerometerUpdates(event => {
          // console.log("event=", event);
          if (this.connected) {
            let data = {
              payloadString: JSON.stringify({ ...event, deviceId: 1 }),
              payloadBytes: null,
              destinationName: topic,
              qos: 0
            };

            console.log("data=", data);
            this.client.publish(new Message(data));
          }
        });
      }
    }
  }
};
</script>

References

mosquitto enable websockets

uniquejava commented 6 years ago

发送到ibm watson iot改动的地方

注意那个clientId格式的坑.

let clientOptions = {
  host: "xxx.messaging.internetofthings.ibmcloud.com",
  port: 1883,
  clientId: "a:xxx:nativescript-vue",
  useSSL: false
};

let client = (this.client = new MQTTClient(clientOptions));

client.connect("a-xxx-fwdfcoq0kn", "afafdfdf");
uniquejava commented 6 years ago

解决窗口最小化后, 抓数据suspend的issue

灵感来自: In IOS 11, DeviceMotion in background stopped working

main.js, 虽然在suspendEvent中调用了相关的service, coremotion内部还是停止了工作.

import * as application from "tns-core-modules/application";

const Vue = require("nativescript-vue");
const App = require("./components/App");
const application = require("tns-core-modules/application");
const motionService = require("~/service/motion-service");

 mounted() {
    console.log("mounted");

    if (application.android) {
      console.log("We are running on Android device!");
    } else if (application.ios) {
      console.log("We are running on iOS device");
    }

    launchListener = application.on(application.launchEvent, args => {
      // The root view for this Window on iOS or Activity for Android.
      // If not set a new Frame will be created as a root view in order to maintain backwards compatibility.
      console.log("Root View: ", args.root);
      console.log("The appication was launched!");
    });
    suspendListener = application.on(application.suspendEvent, args => {
      console.log("The appication was suspended!");
      motionService.restart();
    });
    resumeListener = application.on(application.resumeEvent, args => {
      console.log("The appication was resumed!");
    });
    exitListener = application.on(application.exitEvent, args => {
      console.log("The appication was closed!");
    });
    displayedListener = application.on(application.displayedEvent, args => {
      console.log("NativeScript displayedEvent");
    });
    lowMemoryListener = application.on(application.lowMemoryEvent, args => {
      // the instance that has raidsed the event
      console.log("Instance: ", args.object);
    });
    orientationChangedListener = application.on(application.orientationChangedEvent, args => {
      // orientationChangedEventData.newValue: "portrait" | "landscape" | "unknown"
      console.log("Orientation: ", args.newValue);
    });
    uncaughtErrorListener = application.on(application.uncaughtErrorEvent, args => {
      // UnhandledErrorEventData.error: NativeScriptError
      console.log("NativeScript Error: ", args.error);
    });
  }

在ns中使用event emitter

npm i event-emitter

然后

const ee = require("event-emitter");
class MotionService { ...}
ee(MotionService.prototype);
module.exports = new MotionService();