ESP8266 WebSocket with BlueHost - websocket

Over the past 18 months I have successfully developed an air quality monitoring system that controls an air purifier in my home, I am also using the Blynk platform to monitor and control remotely. Now, I want to migrate this project over to my own website, I have my own website and using standard HTTP commands I now log all the data into a database and graph the data over time.
I want full bi-directional data transfer i.e log data from remote sensors to website and control air purifier settings from website to air purifier. It would appear that one way to do this is by using a webSocket, I have a shared hosting plan with BlueHost so I have now purchased a dedicated ip address and an opened port for both incoming and outgoing connections.
After many hours of trawling the internet and many forums I am struggling to find an example of how to implement this webSocket system. All the examples seem to be for local servers and I cannot find anything that shows what needs to be included in the website end to get a successful connection.
If anyone has any experience with webSockets and BlueHost I would appreciate your help.
Richard

It is relying on what language are you going to use for backend to implement websocket connection no matter what hosting you choosed.
If you want to use PHP, it is pretty straightforward because there is no specific overlay ontop of websocket protocol in this case unlike socketio for NodeJS and others. This example may help you to start which I found in 5 minutes of searching. If you are confused about websocket implementation at all it's a good idea to try websocket for web at first by simple example.
If you want to use NodeJS you may probably want to use existing library something like this.
In case of Java there is SockJS usually used out of the box as standard library for client. So you have to find or make something similar but for C++ if you have enough skills or try to configure simple websocket connection as for PHP.
I have used Firebase library for bidirectional communication with ESP8266, because it is pretty simple and free for small projects. The main benefit of this approach that you don't need to maintain your backend, it just works 24/7 since you've configured connection and business logic. Probably this is what are you looking for. Also you can host static pages on Firebase cloud as well if you need kind of admin interface. Heroku hosting is also free for tiny projects.

#mr.boris
Many thanks for your quick reply and help.
I have been using several examples like your first suggested example, the problem always is that I cannot get passed the "handshake" routine.
Arduino IDE serial monitor output
Connecting to XXXXXXXX
.
WiFi connected
IP address:
192.168.0.110
Connected
Waiting...
Waiting...
Waiting...
Waiting...
Waiting...
Waiting...
Waiting...
Handshake failed.
The port that BlueHost have opened is 1025 could this be the problem?
I have cut done the esp8266 program to the bare minimum
#include <ESP8266WiFi.h>
#include <WebSocketClient.h>
char* WEBSOCKET_PATH = "/webSocket_02.php";
char* WEBSOCKET_HOST = "xxx.com";
char* WIFI_SSID = "xxxxxxxxx";
char* WIFI_PASSWORD = "xxxxxxxxxx";
WebSocketClient webSocketClient;
WiFiClient client;
void setup() {
Serial.begin(115200);
delay(10);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(WIFI_SSID);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
delay(5000);
if (client.connect(WEBSOCKET_HOST,80)) {
Serial.println("Connected");
}
else {
Serial.println("Connection failed.");
}
webSocketClient.path = WEBSOCKET_PATH;
webSocketClient.host = WEBSOCKET_HOST;
if (webSocketClient.handshake(client)) {
Serial.println("Handshake successful");
}
else {
Serial.println("Handshake failed.");
}
}
void loop() {
}
The port number here is 80 (WEBSOCKET_HOST,80), if I change it to 1025 I get no result at all.

Related

Are there any means currently for performing service discovery (mDNS or unicast DND-SD) in nanoframework?

I'm just wondering if there are any means of service discovery built into the nanoframework?
I am mainly interested in mDNS or unicast DNS service discovery. Think Apple Bonjour/Avahi.
I noticed Espressif has some arduino examples around mDNS.
https://github.com/espressif/arduino-esp32/blob/a59eafbc9dfa3ce818c110f996eebf68d755be24/libraries/ESPmDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino
It would make sense as a separate deployment use case when you don't want to connect to a hub in the cloud but instead have the hub (MQTT server) running on the local network and need to discover it.
Many thanks!
Currently there is no support for mDNS in .NET nanoFramework.
But that doesn't seem overcomplicated to add. Please raise an issue with the feature suggestion on our GitHub.
Update 01-01-2023:
Support for mDNS in .NET nanoframework was requested in https://github.com/nanoframework/Home/issues/912. In that discussion, https://github.com/karlredgate/mDNS-sharp was recommended as an alternative to having it built-in into .NET nanoframework. It is not clear whether people succeeded with that, though.
Welcome Cristian!
On an ESP32 you can include multicast DNS and DNS-Service Discovery like that:
#include <ESPmDNS.h>
...
if (MDNS.begin("esp32")) { // access this ESP32 via http://esp32 (eg in browser)
Serial.println("mDNS responder started");
}
...
// register a http-service in DNS-SD
if (mdns_service_add("esp32_website", "_http", "_tcp", 80, NULL, 0)) {
Serial.println("DNS-SD responder started");
}
mdns_service_txt_item_set("esp32_website", "_http._tcp", "version", "1.0");
In order to actually discover the ESP32 and it's services you need to make sure that the machine you are working on supports mDNS and DNS-SD.
Note: mDNS just "resolves" the name of the ESP to it's IP. You need to set-up a webserver on it to actually DO something (like provide the DNS-SD-promised website or such)

Postgresql: No connection could be made because the target machine actively refused it

Running Postgresql 9.5 on a windows server 2012 R2 in Azure
While running some loadtests on my application, I get errors on not being able to connect to the postgres server. In the logs of postgres I get the following message:
could not receive data from client: No connection could be made
because the target machine actively refused it.
This only happens when the loadtest goes to the next scenario, hitting a different part of the code. So new connections to the database are required. But after 10-20 seconds the rest of the scenario works flawlessly without hitting any other hiccups. So the problem seems to be the tcp connections. (My code retries a couple of times but it is not feasible to let it retry for 20 seconds)
I'm using the following settings in the config files
postgresql.conf
listen_addresses = '*'
max_connections = 500
shared_buffers = 1024MB
temp_buffers = 2MB
work_mem = 2MB
maintenance_work_mem = 128MB
pg_hba.conf
host all all 0.0.0.0/0 trust
host all all ::/0 trust
I know, I know.. It is not save to accept connections from everyone, but this is just for testing purposes and to make sure these settings are not blocking any connection. So this answer is void
I've been monitoring the number of connection on the server and under the load it is stable at 75. Postgres is using around 350mb of RAM. So given the config and the vm specs (7gb ram) there should be plenty of space to create more connections. However when the next scenario is spinning up the number of connections does not increase, it stays level and starts giving these log messages about no connection could be made.
What could be the problem here?
It does sound like this isn't really a Postgres problem (hence no changes in DB stats you're checking), rather that the traffic is being stopped by the server. Possibly because traffic on that port is saturated while handling your load testing queries?
It doesn't sound like you're hitting any of the Azure resource limits (including the database limits if that applies to your setup?), but without more detail on your load tests it's hard to say exactly what is needed.
Solutions from around the web and other SO answers suggest:
Disable TCP autotuning and tweak the TCP/IP registry keys on the server, e.g. set TcpAckFrequency - see this article for details
Make TCP setting adjustments (like WinsockListenBacklog) - which may be affected by whether connection pooling is in use or not - see this MS support article, which is for SQL Server 2005 but has some great tips on troubleshooting rejected TCP/IP connections (using Network Monitor, but applies to newer tools)
Faster request processing if you have enough control of the server - source
Disabling network proxying (in your load testing app): <defaultProxy> <proxy usesystemdefault="False"/> </defaultProxy> - source
Most possible reason is a Firewall/Anti-virus:
Software/Personal Firewall Settings
Multiple Software/Personal Firewalls
Anti-virus Software
LSP Layer
(Virtual) Router Firmware
Does your current Azure infrastructure contain Firewall or Anti-virus ?
Additionally on doing some additional searches, it looks like this is a standard Windows "connection refused" message, which suggests that PostgreSQL is trying to connect to something and being refused.
Also possible that one network element in your network - assuming that you are still connected to the server - will delay or drop somes DB login/authentication network packets (considered for example as a fake auth.replay) ...
You may also use a packet analyzer (like Wireshark) to record/inspect network flow when the error appear.
Regards
I was facing the same issue in my AspNet core application while I was trying to connect the Postgresql from my application. The error was thrown in the Program.cs file when I was calling the Migrate function.
public static void Main(string[] args) {
try {
var host = BuildWebHost(args);
using(var scope = host.Services.CreateScope()) {
// Migrate once after app is started.
scope.ServiceProvider.GetService <MyDatabaseContext>().Migrate();
}
host.Run();
}
catch(Exception e) {
//NLog: catch setup errors
_logger ? .Error(e, "Stopped program because of exception: ");
throw;
}
}
To fix this problem I did the following steps.
Check whether the Postgresql service is running by going to the services.msc
Tried to login to the pgAdmin with the user and password I provided in the database context
Everything was file, and as you know that 5432 is the default port of Postgresql and somehow I was using a different port in my application connection string, changing it to 5432 fixed this issue for me.
"ConnectionString": "User Id=postgres;Password=mypwd;Host=localhost;Port=5432;Database=mydb;"
I came across a similar issue whilst trying to beast my api, where I was seeing Npgsql.NpgsqlException No connection could be made because the target machine actively refused it..
However my issue was was down to the fact that I was re-creating my NpgsqlConnection for each query rather than re-using and keeping it alive.

Using Sony Camera API on AndroidWear

I want to create an app that can start and stop recording from a Sony AS100VR camera using camera remote API.
I can get the same working from my nexus using a direct Wifi connection, but when I establish a direct wifi connection from my Sony smartwatch, it fails at the SSDP detection stage.
It's definitely connected to the camera, SSID over Wifi, but it can't detect it.
I have tried playing with retries and timeout values, but I have sort of run out of ideas.
it's falling into the catch catch (InterruptedIOException e) with a java.net.SocketTimeoutException
Any suggestions gratefully appreciated!
UDP Mulitcast is not available on smartwatch, so SSDP discovery fails.
There is a fail-safe choice for any UPnP based application, that is:
As in most case, the resource URL structure keeps unchanged except IP Address, so when SSDP discovery failed, let user directly input the IP Address (maybe in form of UI Picker) and get "DeviceDescription.xml" or something else then setup services.
Have you taken a look at the CameraRemoteSampleApp that comes with the Camera Remote API SDK? I assume when you say Smartwatch you mean you are using a Sony SmartWatch 3 that supports a direct WiFi connection? If so, you should be able to modify the sample app with minimal changes and run it on the SW3.

Is it possible to target a specific Arduino device with the CC3000 Wifi over the web?

I've got my CC3000 Wifi shield and Arduino Uno working as intended using the several libraries, including the aRest.h library. In order for me to control the Arduino from anywhere across the web, I configured the port-forwarding settings on the router to address the Arduino via the routers ip address.
My question is this: If I had a multiple Arduino modules/devices that relied on two way communication (client/server), how is the setup configuration automated for each device so that I could target a specific Arduino with regional data? I don't expect the end user to know how to access the router and configure port forwarding.
I hope this makes sense, I'm a newbie to the world of micro-controllers, but have had some success with progress as of late
You should be able to make a simple way to setup the Wifi, when this job is done you connect via socket so a socket server ( python,node,etc... ) and this will avoid any port-forwarding.
You will not need to care about all this messy tasks, you can have as many as you want arduino in the same network and access from the internet.

Testing Reachability with Network Link Conditioner on 100% packet loss: help me understand what's happening

Help me understand what I am seeing when testing Reachability code using the Network link conditioner. Here is my vanilla Reachability code:
Reachability* wifiReach = [[Reachability reachabilityWithHostName: #"www.apple.com"] retain];
NetworkStatus netStatus = [wifiReach currentReachabilityStatus];
switch (netStatus)
{
case NotReachable:
{
NSLog(#"Access Not Available");
break;
}
case ReachableViaWWAN:
{
NSLog(#"Reachable WWAN");
break;
}
case ReachableViaWiFi:
{
NSLog(#"Reachable WiFi");
break;
}
}
Now, when I test this code using the Network Link Conditioner using the "100% Loss" preset - the value of netStatus is ReachableViaWWAN, which I wasn't expecting. I read a lot of complaints that Reachability doesn't really test connectivity, rather it tests the potential of connectivity. So here's my question:
Is the "100% Loss" preset allowing the DNS requests to the Apple server pass through, but not letting any packets through?
This might have to do with the fact, that Reachability doesn't guarantee that a packet can actually reach the target host. It is about the local network configuration (interface up / down) and if it can SEND a packet.
From Apple's SCNetworkReachability Reference:
A remote host is considered reachable when a data packet, sent by an application into the network stack, can leave the local device. Reachability does not guarantee that the data packet will actually be received by the host.
So if the interface is up and Reachability can send a package, it is satisfied and returns status reachable.
From Apple's developer guide Why Networking is hard:
Important: The SCNetworkReachability API is not intended for use as a preflight mechanism for determining network connectivity. You determine network connectivity by attempting to connect. If the connection fails, consult the SCNetworkReachability API to help diagnose the cause of the failure.

Resources