GithubHelp home page GithubHelp logo

harmony.net's Introduction

Harmony.NET

Harmony.NET is an API that enables local-network websocket communication with Logitech Harmony Hubs. Harmony.NET makes it easy to start and stop activities, press remote buttons, and more in .NET. Built with .NET Standard 2.0, compatible with .NET Core.

To quickly get started, install the package and head down to the quickstart below.

Installation

The easiest way to install Harmony.NET is via NuGet:

Install-Package Harmony.NET

To build from source, clone the repository and build HarmonyHub.sln in Visual Studio. The output files will be located in \HarmonyHub\HarmonyHub\bin\(Debug/Release)\netstandard2.0\Harmony.dll

Usage

Start by importing the library at the top of your file:

using Harmony;

From there, the first step is to get a reference to a Hub. This can be done in three ways

  1. Using a DiscoveryService

    This is the best method to use if you don't know the Hub's IP address beforehand. A DiscoveryService broadcasts a probe over UDP every 5 seconds by default to discover Hubs on the network.

    First, define a new instance of the DiscoveryService:

    DiscoveryService Service = new DiscoveryService();

    Then, subscribe to the event listener HubFound on the service, which is called every time a new Hub is found:

    Service.HubFound += Service_HubFound;

    Finally, start discovery:

    Service.StartDiscovery();

    The event listener will be passed HubFoundEventArgs, which contains a HubInfo property which can be used to create a Hub

    private static async void HubFound(object sender, HubFoundEventArgs e) {
    			Hub Hub = new Hub(e.HubInfo);
    			. . .
    }
  2. Using the Hub's IP Address and ID

    Another way to create a Hub is by using its IP Address and Remote ID.

    These properties can be retrieved from an existing Hub via:

    string IP = Hub.Info.IP;
    string RemoteID = Hub.Info.RemoteId;

    Or HubInfo via:

    string IP = HubInfo.IP;
    string RemoteID = HubInfo.RemoteId;

    To create the Hub, use the constructor:

    Hub Hub = new Hub(IP, RemoteID);
  3. Saving and restoring the Hub with JSON

    You can also save the Hub's state to JSON:

    string Json = Hub.ToJson();

    Then, restore the state using that JSON:

    Hub Hub = Hub.FromJson(Json);

Device IDs

Harmony requires that each client provide a unique ID to communicate with it. The easiest way to get one of these is like so:

DeviceID ClientID = DeviceID.GetDeviceDefault();

However, it is also possible to create a completely custom Device ID just by using its constructor:

DeviceID ClientID = new DeviceID(
	deviceUUID: Guid.NewGuid().ToString("N"),
	deviceProductName: "lg-joan",
	deviceModelName: "lge-h8930"
);

Using the Hub

The first step after obtaining a Hub instance is to connect to it using the DeviceID from earlier:

await Hub.ConnectAsync(ClientID);

Note: ConnectAsync, like most methods in Harmony.NET, is asynchronous. This means you should probably await it in an async function for best performance.

Next, you'll want to retrieve the list of devices and activities on this hub, which can be done using SyncConfigurationAsync:

await Hub.SyncConfigurationAsync();

Note: SyncConfigurationAsync does not return anything, it only updates the Hub itself. To access the raw data, use the Hub.Sync property. It is also unnecessary to call this often. Once every app launch should do.

Controlling individual devices

  1. Getting a device

    There are a few ways to grab an individual Device.

    The first is to look up a device by its model:

    Device Xbox = Hub.GetDeviceByModel("Xbox One", "Microsoft");
    
    // including the manufacturer is not always necessary
    Device Xbox = Hub.GetDeviceByModel("Xbox One");

    The second is to use a known device id:

    // getting the id
    string ID = MyDevice.ID;
    . . .
    // using the id
    Device MyDevice = Hub.GetDeviceById(ID);

    Finally, you can also use the Devices array on a Hub and any LINQ expressions to find exactly what you are looking for.

    Device Newest = Hub.Devices.OrderByDescending(device => device.AddedDate).First();
  2. Controlling a device

    Devices are controlled via functions, akin to buttons on remotes. These Functions can be passed into various methods in the Hub to execute them:

    Function MyFunction = . . .; // see below for details on getting functions
    await Hub.PressButtonAsync(MyFunction);
    
    // hold button for two seconds
    Hub.StartHolding(MyFunction);
    await Task.Delay(2000);
    Hub.StopHolding();

Starting and stopping activities

While all activities are in the Activities array on a Hub, the easiest way to get a reference to one is by using its label or id:

Activity WatchTV = Hub.GetActivityById("12345678");
Activity WatchTV = Hub.GetActivityByLabel("Watch TV");

From there, starting and stopping the activity is trivial:

await Hub.StartActivity(WatchTV);
. . .
await Hub.StopActivity(); // stops the currently running activity, throws if there isn't one

Optionally, if you want to track the progress of stopping or stopping an activity, subscribe to Hub.ActivityProgress:

Hub.ActivityProgress += (sender, e) => {
	// e.progress is a double between 0 and 1
	Console.WriteLine("Starting activity. {0}% done.", Math.Floor(e.Progress * 100));
};

To control an activity, see the section below on retrieving functions

Retrieving functions

The easiest way to get a function is by using a Device Wrapper. A device wrapper provides easy access to commonly used functions.

Note: Despite the name, device wrappers can be used with both activities and devices.

There are currently three wrappers:

  • The simplest one, DeviceWrapper provides power on, off, and toggle power.

  • NumericNavigationWrapper, which inherits from DeviceWrapper, provides the number pad and navigation functions like up, down, select, etc.

  • PlaybackWrapper, which inherits from NumericNavigationWrapper, provides functions like play, skip, etc.

See the examples below for how to use a PlaybackWrapper:

using Harmony.DeviceWrappers;
. . .
PlaybackWrapper DVDWrapper = new PlaybackWrapper(DVDPlayerDevice);
await Hub.PressButtonAsync(DVDWrapper.Play);
PlaybackWrapper PlaybackControls = new PlaybackWrapper(WatchTVActivity); // you can also control activities with wrappers
await Harmony.PressButtonAsync(PlaybackControls.Left);

Alternatively, for functions not available on a wrapper, a function can be retrieved using the GetFunctionByName method on a Controllable object (Device or Activity):

await Hub.PressButtonAsync(DVDPlayerDevice.GetFunctionByName("TopMenu"));

await Hub.PressButtonAsync(WatchTVActivity.GetFunctionByName("Guide"));

Finally, all Functions are available on Controllables either as one array or sorted into ControlGroups

Function Play = Device.GetControlGroupByName("TransportBasic").GetFunctionByName("Play");

// not recommended as these can be unreliable
Function Play = Device.Functions[4]; 
Function Play = Device.ControlGroups[5].Functions[1];

TV Providers

Harmony supports getting information about the user's TV providers and their channels.

First, you'll need to download information about the user. This includes the user's location, and TV provider and favorite channels for particular devices.

User User = await Hub.GetUserInfo();

Next, get the TV providers for a specific device, say a DirecTV DVR, and download the main provider's channels

// Get channels on DVR TV provider
ProviderList DirecTVProviders = User.Preferences.GetProvidersForDevice(DirecTV);

// There's usually only one provider per device, so just get the default
ProviderInfo ProviderInfo =	await Hub.GetInfoForProvider(DirecTVProviders.DefaultProviderId);

Once you have the provider's channels, you can access data like channel numbers, names, and popularity. For example, here's how to tune to the most popular channel:

Channel MostPopular = ProviderInfo.PopularChannels.First();
await Hub.ChangeChannel(MostPopular);
Console.WriteLine("Tuned to channel {0}", MostPopular.Station.FullName);

Or to tune to ESPN:

Channel ESPN = ProviderInfo.GetChannelByStationShortName("ESPN");
await Hub.ChangeChannel(ESPN);

Or a favorite channel:

string FavoriteChannelId = DirecTVProviders.DefaultFavoriteChannels.StationIDs.First();
Channel Favorite = ProviderInfo.GetChannelByStationID(FavoriteChannelId);
await Hub.ChangeChannel(Favorite);

Note that if you know the channel number in advance, you don't have to go through all of the steps above to tune to it.

await Harmony.ChangeChannel("206");

Sending Multiple Functions in a Row

Harmony has an issue (or perhaps a feature) that prevents sending commands at regular intervals. For example, the third command will not be executed in the code below:

// broken
await Hub.PressButtonAsync(Wrapper.Up);
await Task.Delay(400);
await Hub.PressButtonAsync(Wrapper.Right);
await Task.Delay(400);
await Hub.PressButtonAsync(Wrapper.Select);

To fix this issue, Hub has a method PressButtonsAsync (note the "s") which allows sending multiple commands at a semi-regular interval:

// takes either a params Function array
await Hub.PressButtonsAsync(400, Wrapper.Number0, Wrapper.Number1, Wrapper.Number2);

// or an IEnumerable<Function>
await Hub.PressButtonsAsync(400, WatchTV.Functions.Where(fn => fn.Name.StartsWith("Number")));

The example above is equivalent to the following code (400ms difference between each call):

// works!
await Hub.PressButtonAsync(Wrapper.Number0);
await Task.Delay(600);
await Hub.PressButtonAsync(Wrapper.Number1);
await Task.Delay(200);
await Hub.PressButtonAsync(Wrapper.Number2);

This +/- 200ms adjustment can be changed by setting Hub.RepeatedCommandAdjustment to any ms value. Setting it to 0 will disable this feature.

Quickstart

This quickstart demonstrates discovering a hub, starting an activity, and tuning to a channel

DiscoveryService Service = new DiscoveryService();
Service.HubFound += async (sender, e) => {
	// stop discovery once we've found one hub
	Service.StopDiscovery();

	Hub Harmony = new Hub(e.HubInfo);
	await Harmony.ConnectAsync(DeviceID.GetDeviceDefault());
	await Harmony.SyncConfigurationAsync();

	// start activity watch tv
	Activity WatchTV = Harmony.GetActivityByLabel("Watch TV");
	await Harmony.StartActivity(WatchTV);

	// tune to ESPN
	await Harmony.ChangeChannel("206");
	PlaybackWrapper PlaybackControls = new PlaybackWrapper(WatchTV);

	// wait for channel to switch, and pause
	await Task.Delay(1000);
	await Harmony.PressButtonAsync(PlaybackControls.Pause);
};
Service.StartDiscovery();

Issues and Suggestions

If you have any problems or features you'd like to see me add to Harmony.NET, I'd be happy to hear about them. Please make a new issue

License

This project is licensed under the MIT License. See more information in the LICENSE file.

Copyright

Copyright 2018 (c) John Lynch

harmony.net's People

Contributors

bluewalk avatar jlynch630 avatar zrdelano avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

harmony.net's Issues

RemoteId without discovery?

If I know the IP address, is there a way to instantiate the Hub without knowing what the RemoteId is? Or is there another way for us to get that?

"Hub closed the connection unexpectedly"

Hello,
i tried your Sample Code, but i have problems

`public MainWindow()
{
InitializeComponent();

        DiscoveryService Service = new DiscoveryService();
        Service.HubFound += async (sender, e) => {
            // stop discovery once we've found one hub
            Service.StopDiscovery();

            Hub Harmony = new Hub(e.HubInfo);
            await Harmony.ConnectAsync(DeviceID.GetDeviceDefault());
            await Harmony.SyncConfigurationAsync();

            // start activity watch tv
            Activity WatchTV = Harmony.GetActivityById("12524412");
            await Harmony.StartActivity(WatchTV);

        };
        Service.StartDiscovery();

    }`

image

image

Harmony.HarmonyException
HResult=0x80131500
Nachricht = Hub closed the connection unexpectedly
Quelle = Harmony
Stapelüberwachung:
bei Harmony.WebSockets.HubConnection.d__11.MoveNext() in C:\SVN\Hausautomation\Visu\branches\HarmonyTest\Harmony.NET-master\Harmony\WebSockets\HubConnection.cs: Zeile119
bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei System.Runtime.CompilerServices.TaskAwaiter1.GetResult() bei Harmony.Hub.<SyncConfigurationAsync>d__72.MoveNext() in C:\SVN\Hausautomation\Visu\branches\HarmonyTest\Harmony.NET-master\Harmony\Hub.cs: Zeile422 bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
bei HarmonyTest.MainWindow.<>c__DisplayClass0_0.<<-ctor>b__0>d.MoveNext() in

what im doing wrong?
Many thanks

Markus

Switch to another WebSocket client library

The .NET WebSocket client implementation varies between the Framework and Core. In fact, the .NET Framework version is incompatible with this library. WebSocketSharp seems promising. See issue #2

Implement events for home automation

Events like "automation.state?notify" are currently not implemented due to the variety of their payloads. However, these can probably be added in the form:

Hub.OnAutomationStateUpdated += (Dictionary<string, dynamic/JSON string> devices) => {

}

which will be passed a dictionary with keys representing devices ids, like "hue-mac:address" and values with their payload data either as a dynamic object or as a JSON string

Unsolicited incoming messages

Is it possible to pick up on and react to incoming messages? For instance if I start an activity using my remote, Harmony.Net receives the messages and fires events based on them?

I had this implemented in my XMPP app for this, but I'm new to clientwebsocket and not sure how to just listen to incoming messages so I can react to them.

For instance be notified when an activity is started from the remote instead of from Harmony.net

Question - On Button Pressed Event

Is there any functionality in the Harmony Hub locally that can notify you when a button like "pause" was pressed on the remote? If so, do you have an example of how to implement this in your code? Thank you!

GetRunningActivity should not return null

GetRunningActivity should not return null, because '-1' is a valid id and 'null' is not a valid activity.
It should instead return the 'PowerOff' activity or atleast something that represents the poweroff activity.

return RunningActivityId != "-1" ? this.GetActivityById(RunningActivityId) : null;

SocketException in .NET Core App

Looks like any .net core app I run this in, I end up with:

Unhandled Exception: System.Net.Sockets.SocketException: Operation not supported
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, Int32 optionValue, Boolean silent)
   at System.Net.Sockets.Socket.SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, Int32 optionValue)
   at System.Net.Sockets.Socket.set_DontFragment(Boolean value)
   at Harmony.DiscoveryService.BroadcastTo(String ipAddress)
   at Harmony.DiscoveryService.Broadcast()
   at Harmony.DiscoveryService.BroadcastContinually(CancellationToken token)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---

It works fine on a standard .NET console app.

Discover uses HubID which is not unique

When discovering Hubs, you use HubID form the response to determine if you have it. HubID does not seem to be unique (at least not for me). Across my 5 Hubs, I have only 2 HubIds. 106 and 97.

I suggest you use the UUID instead as these are truly unique.

Command queues

I saw you had a note about commands executed in sequence and 400ms spacing or the harmony would ignore them or something? When you get a chance can you elaborate on that? I'm thinking like the case of someone sending multiple commands not through that interface, but directly one by one and going faster than this rate. Whats the reasoning for the rate limiting there, and if there's a limitation, would it make sense to introduce some sort of queueing to command message sending?

Hub.State always null

Hub.State is always null, even after calling hub.SyncConfigurationAsync();. Hitting this when calling hub.GetRunningActivity().

Background: simple console app to get the running activity and when my I switch my domotics to Night-Mode it should return the status and if different than -1 (Off) it should activate the -1 activity. Is it because the console app is not open for a long enough time to receive the connect.statedigest?get or connect.statedigest?notify commands?

WebSocketException during ConnectAsync

Hi,

when I call ConnectAsync(clientID) I get this exception:

System.Net.WebSockets.WebSocketException (0x80004005): 'Connection' header value 'upgrade,keep-alive' is invalid

Any Ideas? The Hub has upgraded a few days ago to the newest firmware. I am using .NET 4.6.1 with VS 2017.

UPDATE: .NET 4.7 is not working, but the same code works with .NET Core 2.1.

Best regards
Christoph

After Disposing ReceiveHarmonyMessage fails

After disposing the hub/connection, 'ReceiveHarmonyMessage' fails because it is already awaiting while the connection was closed. Resulting in a parsing exception because 'Message' is empty.
Exception:
Newtonsoft.Json.JsonReaderException: Error reading JObject from JsonReader. Path '', line 0, position 0.
Source:
string Message = await this.ReceiveMessage(); JObject MessageObject = JObject.Parse(Message);

having trouble

trying to implement in vb.net. I am self taught and possibly doing it wrong but I don't think I am.
hub

Here is my code.

Sub Main(args As String())

    Dim hub As New Hub("10.1.1.13", "18117167")
    Dim ClientID As DeviceID = DeviceID.GetDeviceDefault

    hub.ConnectAsync(ClientID)
    hub.SyncConfigurationAsync()

....

Connection to myharmony.com?

I noticed that the library is connecting to either *.myharmony.com or *.dhg.myharmony.com, any idea where and why this is happening? It only appears the first minute when doing a discovery.

image

Upon checking the IP addresses (34.192.104.176 and 52.7.206.211 for now):

image

IP Loopback

Found that this library did not work when deployed to a raspberry pi. This seemed to be due to the local IP address lookup returning a list with the loopback address as the first IP address and this being used for the probe.

If you change line 97 in DiscoveryService.cs from

if (IP.AddressFamily == AddressFamily.InterNetwork)

to

if (IP.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(IP))

the library then worked on the raspberry.

IDisposable implementation

If I'm not mistaken, your Hub (and maybe HubConnection) could use an IDisposable implementation to ensure proper cleanup of connections.

Error on Dispose()

Calling Dispose() on the Hub will call Dispose() on WebSocketConnection and result in:
System.Net.WebSockets.WebSocketException: "The remote party closed the WebSocket connection without completing the close handshake."

Am I doing something wrong (netcore 2.1)?

RFC: Exceptions

I am not here to critize in fact I want to thank everybody who contributed, especially jlynch.
But I would like to talk about the concept / usage of exceptions.
There are multiple ways to handle failure:

  • Throwing Exceptions:
    Wich lead to quite unpredictable behaviour and seamingly 'random' crashes.
    Handling them usually results in splatterning try/catch all over the code as soon as a new exception surfaces or even preemptively. These usually just eat/disable the exception or rethrow it keeping the problem alive.
  • Returning null:
    This is better (imo) because it keeps the function working in all circumstances.
    But the caller will have to have null checks everywhere or risk failing,
    because those checks are not enforced. Also you won't get any kind of error information.
  • Returning success (and result):
    This could be a boolean or a tuple of boolean and result. Wich comunicates to the user that the function could fail and that the user should check before proceeding.
    But it still looses the error info and does not enforce checking.
  • Returning an option type (choice):
    This is the way it is done in F#. It would return an option<'a> or nothing (not null).
    It allows a function that will always work, does not require try/catch or null checking and
    communicates clearly to the user. Still discards error info, but this can be added easily.
    As far as I know there is no inbuild why to do this in c#. So It will have to be made.

I am suggesting this because websockets seem to love throwing exceptions,
wich reduces reliability, usability and as an F# dev this is quite annoying.

Is there a better c# way I am missing?
Any suggestions?

Not automatically reconnecting

Over time, or when I reboot a switch or AP the library loses connection to the Hub (makes sense right?).
I see there's a TODO about reconnecting upon read failure in StartListening. Any idea on when it will be implemented?

When the connection breaks the following exception is generated

Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Net.Sockets.SocketException
   at System.Net.Sockets.Socket.BeginSend(Byte[], Int32, Int32, System.Net.Sockets.SocketFlags, System.AsyncCallback, System.Object)
   at System.Net.Sockets.NetworkStream.BeginWrite(Byte[], Int32, Int32, System.AsyncCallback, System.Object)

Exception Info: System.IO.IOException
   at System.Net.Sockets.NetworkStream.BeginWrite(Byte[], Int32, Int32, System.AsyncCallback, System.Object)
   at System.IO.Stream+<>c.<BeginEndWriteAsync>b__53_0(System.IO.Stream, ReadWriteParameters, System.AsyncCallback, System.Object)
   at System.Threading.Tasks.TaskFactory`1[[System.Threading.Tasks.VoidTaskResult, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].FromAsyncTrim[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.IO.Stream+ReadWriteParameters, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](System.__Canon, ReadWriteParameters, System.Func`5<System.__Canon,ReadWriteParameters,System.AsyncCallback,System.Object,System.IAsyncResult>, System.Func`3<System.__Canon,System.IAsyncResult,System.Threading.Tasks.VoidTaskResult>)
   at System.IO.Stream.BeginEndWriteAsync(Byte[], Int32, Int32)
   at System.IO.Stream.WriteAsync(Byte[], Int32, Int32, System.Threading.CancellationToken)
   at System.Net.WebSockets.Managed.ManagedWebSocket.SendFrameLockAcquiredNonCancelableAsync(MessageOpcode, Boolean, System.ArraySegment`1<Byte>)

Exception Info: System.Net.WebSockets.WebSocketException
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
   at System.Net.WebSockets.Managed.ManagedWebSocket+<SendCloseFrameAsync>d__68.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
   at System.Net.WebSockets.Managed.ManagedWebSocket+<CloseAsyncPrivate>d__67.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
   at Harmony.WebSockets.WebSocketConnection+<Disconnect>d__6.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
  ...

problem with method Connect

hello, when I try to connect to the hub i receive the following exception:

The 'Connection' header value 'upgrade,keep-alive' is invalid.

on this line:

HubConnetion.cs --> await this.WebSocket.ConnectAsync(new Uri(FullUrl), CancellationToken.None);

with the following stack trace:

at System.Net.WebSockets.ClientWebSocket.ValidateResponse(HttpWebRequest request, HttpWebResponse response)
at System.Net.WebSockets.ClientWebSocket.d__21.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Harmony.HubConnection.d__3.MoveNext()

have you any Idea of how can prevent this exception:

Harmony hub info:
CurrentFirmwareVersion 4.15.193

thank you,

luca

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.