ilcato / homebridge-blynk

Homebridge plugin for the Blynk platform
MIT License
20 stars 30 forks source link

Thanks for the initiative! #1

Closed blynkkk closed 8 years ago

blynkkk commented 8 years ago

Just came across your work in progress. Let us know if we can help with something.

Looking forward to starting using this plugin and spreading the word about it

ilcato commented 8 years ago

I'm trying to build a first usable version. Just added read support for switch. I plan to have such a version in a few days. It could be useful to have an api on the server to look for changes in order to automatically update the homekit status. Currently the only option I have is to perform a periodic polling on all pins -> to heavy.

doom369 commented 8 years ago

Do you mean webhook on pin change?

ilcato commented 8 years ago

Yes

ilcato commented 8 years ago

@blynkkk : how do I refer to a physical pin through the Rest API. I'm able to read and write to a virtual pin. But what is the syntax for physical one (digital and analog)? Is it D1, D2, ... and A1, A2, ... or GP1, GP2 as in the Blynk app?

doom369 commented 8 years ago

Is it D1, D2, ... and A1, A2

yes.

ilcato commented 8 years ago

@doom369 : is it correct the following behavior?

If this is correct I don't think we can use Homekit.

doom369 commented 8 years ago

Do you mean physical button? If so you need to wrap digital pin with virtual pin. And when you press physical button you need to send Blynk.virtualWrite(); Have a look in sketches we provide.

ilcato commented 8 years ago

This way, right?

BLYNK_READ(V2) { int val = digitalRead(D2); Blynk.virtualWrite(V2, val); }

doom369 commented 8 years ago

yes. you can also use button interrupt, so no need to have a timer on app.

ilcato commented 8 years ago

BLYNK_READ(V2) is called when the Blynk app is running and there's a Value Display widget associate to V2. If I only have the REST client calling the Blynk Server for reading V2 it receives the last value polled by the app. What I need in order to have, for example, an HomeKit accessory of type ContactSensor associated to a virtual (or physical) pin is a REST call that function without the Blynk app running.

doom369 commented 8 years ago

https://github.com/blynkkk/blynk-library/blob/master/examples/More/ButtonInterrupt/ButtonInterrupt.ino https://github.com/blynkkk/blynk-library/blob/master/examples/More/ButtonPoll/ButtonPoll.ino

ilcato commented 8 years ago

Yes, this is what I'm trying to avoid. What I'd like to have is a mechanism similar to the one adopted for the Blynk App widget: the app calls "something on the server" and is able to retrieve the value of the pins (virtual, digital, ...).

doom369 commented 8 years ago

This is not implemented for REST API. But you could use for this case websockets.

ilcato commented 8 years ago

Is there a socket entry point in Blynk server ?

doom369 commented 8 years ago

Here is example https://github.com/blynkkk/blynk-server/tree/master/docs/websocket and here https://github.com/tzapu/node-red-contrib-blynk-websockets

ilcato commented 8 years ago

I completely missed the server repository. I just downloaded the server binaries.

I will look this further info.

Thank you

doom369 commented 8 years ago

Have fun =)

ilcato commented 8 years ago

@doom369, in my understanding with the script that you indicated I'm able to perform an hardware role with respect to the Blynk server. Is it right? What I'm looking for is to have the ability to execute like the Blink App in order to control the Blynk devices.

doom369 commented 8 years ago

Is it right?

Yes.

What I'm looking for is to have the ability to execute like the Blink App in order to control the Blynk devices.

Could you please describe exactly and detailed use case you want to achieve? I'm afraid I don't understand your goals.

ilcato commented 8 years ago

Ok, I want to be able to control Blynk hardware through HomeKit and Siri. So, for example, in order to have the ability to ask Siri something like "what's the temperature in the living room?" (provided there's a temperature sensor connected to a pin on an Arduino) I need an API on the Blynk server that allows to query the value of the pin. This is what the REST API is supposed to do I think, but in my experiment this is true only if there's the Blynk App running that polls (with the set frequency) the given pin.

doom369 commented 8 years ago

Ok. Got it. So yes. This is true for polling and this is how polling suppose to work. Polling is application based, not server side. However it is possible to achieve what you want. All you need to do is

Blynk.virtualWrite(V5, value);

whenever you think it is required in your code. Here is a basic example of how to write value every second.

And you can call at any time HTTP GET request in order to get latest value for V5.

ilcato commented 8 years ago

Understood. And what about the "-mode app" in the Java Blync client ? What is it suppose to do? Isn't it possible to go that way in order to be able to query the server the same way the Blynk app do?

doom369 commented 8 years ago

Yes, you can do that with Blynk client, but it was designed only for integration tests in order to simulate Blynk apps. So it has no documentation, guides, etc.

ilcato commented 8 years ago

Ok. I will check this path. It has minor impact on the way in which you build Things.

doom369 commented 8 years ago

Have in mind. Client will work only for local server as we use mutual SSL on Blynk Cloud.

ilcato commented 8 years ago

Ok. A side question, why didn't you adopt existing IoT protocol like MQTT ?

doom369 commented 8 years ago

Few reasons :

We will add MQTT support for hardware side soon. But at the moment we have only few users who care about that.

ilcato commented 8 years ago

@doom369: it seems that the following https://github.com/blynkkk/blynk-library/blob/master/scripts/blynk_ctrl.py may be the right answer to my need.

doom369 commented 8 years ago

Nice. Looking forward to see working prototype.

ilcato commented 8 years ago

@doom369: I dismiss the "bridge" approach of the blynk_ctrl.py because it present the same problem of the other approaches I test. I switched back to the idea of implementing a client app approach on the TCP SSL entry point (the same of the Blynk app). I was able to write a node.js module that implement the capability. Now I have all the building blocks for completing the homebridge plugin for the HomeKit/Siri access to Blynk.

In the mean time I just published the node.js module on npm: blynk-app-client. It is a very first draft that I will update with the lesson learned in writing the homebridge plugin.

doom369 commented 8 years ago

@ilcato cool. You are awesome. Thanks for sharing!

ilcato commented 8 years ago

@doom369: blynk-app-client module is now pretty complete for my scope.

ilcato commented 8 years ago

@blynkkk, @doom369 : for the homekit/Siri integration I have reached a road block. Situation:

For example: if I have digital pin 5 connected to a Button and I try to read its value through the hardware command, like

blynk.hardware(101, "d", "r", 5);

it fails because it is looking for a FrequencyWidget connected to the same pin, that is impossible because it is already connected to the Button Widget that is not a FrequencyWidget.

In HardwareAppLogic.java row 69 there's:

        case 'r' :
            FrequencyWidget frequencyWidget = dash.findReadingWidget(split[1].split(StringUtils.BODY_SEPARATOR_STRING), message.id);
            if (frequencyWidget.isTicked(split[1])) {
                session.sendMessageToHardware(ctx, dashId, new HardwareMessage(message.id, split[1]));
            }
            break;

If I modify the logic in:

        case 'r' :
            FrequencyWidget frequencyWidget = dash.findReadingWidget(split[1].split(StringUtils.BODY_SEPARATOR_STRING), message.id);
            if (frequencyWidget) frequencyWidget.isTicked(split[1]);
            session.sendMessageToHardware(ctx, dashId, new HardwareMessage(message.id, split[1]));
            break;

and in DashBoard.java row 104 I modify it in the following way:

from

    throw new IllegalCommandBodyException("No frequency widget for read command.", msgId);

to

    return null;

it works and it also update the LastRequestTS if necessary.

Are you able to check if this (or a similar change) is possible to introduce in the Blynk server?

Thanks.

doom369 commented 8 years ago

Option 1: the Blynk rest API (the first I tried). This approach fails because it requires the Blynk mobile app running

It doesn't. Code.

Suggested change is not correct from point of view of server. Button is not supposed to send reading command. The only way at the moment would be to use HTTP API.

Do you use Blynk cloud? Could you please explain why you think HTTP API doesn't work without running app?

ilcato commented 8 years ago

@doom369, I'm using local Blynk server. I access digital pin number 4 with a GET request on:

https://10.0.0.102:9443/f8fc77e07d6b415984f683ccd9bd2e4a/pin/D4

It respond with the last value presented on widget display on the Dashboard on the mobile app when the dashboard was running.

If it is running the previous GET always respond correctly but as soon as I stop the Dashboard, put the app in the background or kill it the GET request respond with the last value read by the widget while the app was running.

I think that the reason is because in the REST API you simply return the value stored in the Widget in the Dashboard while in the App API you "sendMessageToHardware" in order to retrieve the value directly from the board. If the App is running it periodically read the value from the board and stores it in the widget.

doom369 commented 8 years ago

You are right. I'll think what we can do here.

ilcato commented 8 years ago

@doom369: any news?

doom369 commented 8 years ago

Not yet. Busy with next release.

doom369 commented 8 years ago

https://github.com/blynkkk/blynk-server/issues/118 will try to resolve it today

ilcato commented 8 years ago

great!

doom369 commented 8 years ago

@ilcato I spent few hours in order to find best solution, but I'm afraid implementation of such HTTP API may cause performance issues due to async nature of Blynk server. Your polling solution is only possible at the moment. I hope we will introduce WebHooks very soon so your solution may be simplified.

ilcato commented 8 years ago

@doom369: let me try to recap.

In order to finalize the homebridge-blynk plugin I need to have the possibility to read and write a pin. Consider this scenario:

Please try to reconsider the change that I proposed two weeks ago that I propose as a pull request on the Blynk server. In this way all works as I expected.

doom369 commented 8 years ago

the plugin needs also to be able to manage Siri queries like "Is the lamp turned on ?". For this query I need to read the value of pin 5. This is not possible if I already associated the pin to a Blynk controller widget.

This is possible if you will send Blynk.virtualWrite on pin change to server, so server will always have latest state.

ilcato commented 8 years ago

But this limits the scope to the virtual pins and needs to implement logic on the device side.

doom369 commented 8 years ago

Indeed virtual pins where designed exactly for such cases.

and needs to implement logic on the device side.

yeah =).

I'll accept your proposal in PR and will release update soon.

doom369 commented 8 years ago

@ilcato released 0.13.2

ilcato commented 8 years ago

@doom369, @blynkkk I'm glad to announce the first usable version of the homebridge-blynk plugin. Please have a try and ask Siri to "turn on the computer" !

doom369 commented 8 years ago

Nice!

blynkkk commented 8 years ago

super cool! thanks! :pray: Will test it out on a weekend.

@ilcato Do you have a "getting started" somewhere?

ilcato commented 8 years ago

@blynkkk, basically:

For the config file:

{ "name": "SwitchD5", "widget": "Switch", "mode": "SWITCH", "caption": "Lamp 1", "pin": "D5" }

where:

Use an HomeKit app to add the accessory to the iPhone/iPad, e.g.: MyHome

After that you can say to Siri:

turn on lamp 1