Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Panasonic Viera TV remote control #2137

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added Sming/Libraries/DIAL/.cs
Empty file.
8 changes: 8 additions & 0 deletions Sming/Libraries/DIAL/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
DIAL protocol
=============

Introduction
------------

DIAL—for DIscovery And Launch—is a simple protocol that second-screen devices can use to discover and launch apps on first-screen devices.
For example, your can stream a video from your embedded device on your connected TV.
3 changes: 3 additions & 0 deletions Sming/Libraries/DIAL/component.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
COMPONENT_SRCDIRS := src/Dial
COMPONENT_INCDIRS := src/
COMPONENT_DEPENDS := UPnP SSDP
28 changes: 28 additions & 0 deletions Sming/Libraries/DIAL/sample/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>DIAL_Client</name>
<comment></comment>
<projects>
<project>SmingFramework</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>
9 changes: 9 additions & 0 deletions Sming/Libraries/DIAL/sample/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#####################################################################
#### Please don't change this file. Use component.mk instead ####
#####################################################################

ifndef SMING_HOME
$(error SMING_HOME is not set: please configure it as an environment variable)
endif

include $(SMING_HOME)/project.mk
4 changes: 4 additions & 0 deletions Sming/Libraries/DIAL/sample/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Control your DIAL-enabled smart monitor/TV using Sming
======================================================

Demonstrates starting of YouTube, playing a video and closing YouTube after a small period of time.
92 changes: 92 additions & 0 deletions Sming/Libraries/DIAL/sample/app/application.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#include <SmingCore.h>
#include <Dial/Client.h>

// If you want, you can define WiFi settings globally in Eclipse Environment Variables
#ifndef WIFI_SSID
#define WIFI_SSID "PleaseEnterSSID" // Put you SSID and Password here
#define WIFI_PWD "PleaseEnterPass"
#endif

Dial::Client client;

void onRun(Dial::App& app, HttpResponse& response)
{
auto responseCode = response.code;
if(responseCode < 400) {
auto timer = new AutoDeleteTimer;
timer->initializeMs<20000>([&]() {
// Once started the app can also be stopped using the command below
Serial.printf(_F("Stopping application: %s\n"), app.getName().c_str());
app.stop();
});
timer->startOnce();
}
}

void onStatus(Dial::App& app, HttpResponse& response)
{
auto responseCode = response.code;
if(responseCode == HTTP_STATUS_NOT_FOUND) {
Serial.printf(_F("Unable to find the desired application: %s\n"), app.getName().c_str());
return;
}

HttpParams params;
params["v"] = "fC9HdQUaFtA";
app.run(params, onRun);
}

void onConnected(Dial::Client& client, const XML::Document& doc, const HttpHeaders& headers)
{
CStringArray path("device");
path.add("friendlyName");
auto node = client.getNode(doc, path);
Serial.println(_F("New DIAL device found."));
if(node != nullptr) {
Serial.printf(_F("Friendly name: %s.\n"), node->value());
}

auto app = client.getApp("YouTube");
app->status(onStatus);
}

void connectOk(IpAddress ip, IpAddress mask, IpAddress gateway)
{
Serial.print(_F("I'm CONNECTED to "));
Serial.println(ip);

/* The command below will use UPnP to auto-discover a smart monitor/TV */
client.connect(onConnected);

/* Alternatevely one can use the commands below when auto-discovery is not working */
/*
Url descriptionUrl{"192.168.22.222:55000/nrc/ddd.xml"};

client.connect(descriptionUrl, onConnected);
*/
}

void connectFail(const String& ssid, MacAddress bssid, WifiDisconnectReason reason)
{
// The different reason codes can be found in user_interface.h. in your SDK.
Serial.print(_F("Disconnected from \""));
Serial.print(ssid);
Serial.print(_F("\", reason: "));
Serial.println(WifiEvents.getDisconnectReasonDesc(reason));
}

void init()
{
Serial.begin(SERIAL_BAUD_RATE);
Serial.systemDebugOutput(true); // Allow debug print to serial

// Station - WiFi client
WifiStation.enable(true);
WifiStation.config(_F(WIFI_SSID), _F(WIFI_PWD));

// Set callback that should be triggered when we have assigned IP
WifiEvents.onStationGotIP(connectOk);

// Set callback that should be triggered if we are disconnected or connection attempt failed
WifiEvents.onStationDisconnect(connectFail);
}
3 changes: 3 additions & 0 deletions Sming/Libraries/DIAL/sample/component.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ARDUINO_LIBRARIES := DIAL

DISABLE_SPIFFS = 1
112 changes: 112 additions & 0 deletions Sming/Libraries/DIAL/src/Dial/App.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#include "App.h"

namespace Dial
{
HttpClient App::http;

bool App::status(ResponseCallback onResponse)
{
auto request = new HttpRequest(applicationUrl);
request->method = HTTP_GET;
request->setResponseStream(new LimitedMemoryStream(maxDescriptionSize));
if(onResponse != nullptr) {
request->onRequestComplete([onResponse, this](HttpConnection& connection, bool successful) -> int {
onResponse(*this, *(connection.getResponse()));

return 0;
});
}

return http.send(request);
}

bool App::run(ResponseCallback onResponse)
{
auto request = new HttpRequest(applicationUrl);
request->method = HTTP_POST;
request->setResponseStream(new LimitedMemoryStream(maxDescriptionSize));
request->onRequestComplete([onResponse, this](HttpConnection& connection, bool successful) -> int {
auto headers = connection.getResponse()->headers;
if(headers.contains(HTTP_HEADER_LOCATION)) {
this->instanceUrl = headers[HTTP_HEADER_LOCATION];
}

if(onResponse != nullptr) {
onResponse(*this, *(connection.getResponse()));
}

return 0;
});

return http.send(request);
}

bool App::run(const String& body, enum MimeType mime, ResponseCallback onResponse)
{
auto request = new HttpRequest(applicationUrl);
request->method = HTTP_POST;
request->headers[HTTP_HEADER_CONTENT_TYPE] = ContentType::toString(mime);
if(body.length() != 0) {
request->setBody(body);
}
request->setResponseStream(new LimitedMemoryStream(maxDescriptionSize));
request->onRequestComplete([onResponse, this](HttpConnection& connection, bool successful) -> int {
auto headers = connection.getResponse()->headers;
if(headers.contains(HTTP_HEADER_LOCATION)) {
this->instanceUrl = headers[HTTP_HEADER_LOCATION];
}

if(onResponse != nullptr) {
onResponse(*this, *(connection.getResponse()));
}

return 0;
});

return http.send(request);
}

bool App::run(const HttpParams& params, ResponseCallback onResponse)
{
auto request = new HttpRequest(applicationUrl);
request->method = HTTP_POST;
request->setPostParameters(params);
request->setResponseStream(new LimitedMemoryStream(maxDescriptionSize));
request->onRequestComplete([onResponse, this](HttpConnection& connection, bool successful) -> int {
auto headers = connection.getResponse()->headers;
if(headers.contains(HTTP_HEADER_LOCATION)) {
this->instanceUrl = headers[HTTP_HEADER_LOCATION];
}

if(onResponse != nullptr) {
onResponse(*this, *(connection.getResponse()));
}

return 0;
});

return http.send(request);
}

bool App::stop(ResponseCallback onResponse)
{
if(instanceUrl.length() == 0) {
debug_w("Instance URL not set. Only started apps can be stopped.");
return false;
}

auto request = new HttpRequest(Url(instanceUrl));
request->method = HTTP_DELETE;
request->setResponseStream(new LimitedMemoryStream(maxDescriptionSize));
if(onResponse != nullptr) {
request->onRequestComplete([onResponse, this](HttpConnection& connection, bool successful) -> int {
onResponse(*this, *(connection.getResponse()));

return 0;
});
}

return http.send(request);
}

} // namespace Dial
45 changes: 45 additions & 0 deletions Sming/Libraries/DIAL/src/Dial/App.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include <SmingCore.h>

namespace Dial
{
class App
{
public:
using ResponseCallback = Delegate<void(App& app, HttpResponse& response)>;

App(const String& name, const Url& appsUrl, size_t maxDescriptionSize = 2048)
: name(name), maxDescriptionSize(maxDescriptionSize)
{
applicationUrl = Url(appsUrl.toString() + '/' + name);
instanceUrl = applicationUrl;
}

String getName()
{
return name;
}

bool status(ResponseCallback onResponse);

/**
*
*/
bool run(ResponseCallback onResponse = nullptr);

bool run(const String& body, enum MimeType mime, ResponseCallback onResponse = nullptr);

bool run(const HttpParams& params, ResponseCallback onResponse = nullptr);

bool stop(ResponseCallback onResponse = nullptr);

private:
String name;
Url applicationUrl;
String instanceUrl;
size_t maxDescriptionSize;
static HttpClient http;
};

} // namespace Dial
Loading