Is the detection of an Interrupt totally dependent on type e.g. level or edge? - .net-micro-framework

Page 36 EMX User Manual states: "Interrupts can be activated on rising or falling edges with an optional glitch filter." However Redpine Signals RS9110-N-11-21 Datasheet states: "Active high, level triggered."
The interrupt is triggered by the WiFi device. Within the C# code if I use a parameter of InterruptEdgeLevelHigh or InterruptEdgeLevelLow I receive an Argument Exception. That is ok as it agrees with the EMX user manual. If I use InterruptEdgeBoth, InterruptEdgeHigh or InterruptEdgeLow I cannot receive a interrupt. I am not sure if this is because the device is using "Active high, level triggered".
If RedPine are limited to "level triggered" should I be able to detect their interrupts with Edge triggered anyway or is the interrupt detection absolutely restricted to Level?
Here is part of the code that I am using to test the trigger:
public static void Main()
{
config = new SPI.Configuration((Cpu.Pin)EMX.Pin.IO2, false, 0, 0, false, true, 1000, SPI.SPI_module.SPI1);
SPI1 = new SPI(config);
WiFiReset = new OutputPort((Cpu.Pin)EMX.Pin.IO3, true);
WiFiInterrupt = new InterruptPort((Cpu.Pin)EMX.Pin.IO26, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeHigh);
// "Interrupts can be activated on rising or falling edges with an optional glitch filter." Page 36 EMX User Manual.
// Redpine Datasheet: "Active high, level triggered."
// NETMF interrupt event: "If an InterruptEdgeLevelHigh or InterruptEdgeLevelLow interrupt event occurs, an application must call the ClearInterrupt method to re-enable this event."
WiFiInterrupt.OnInterrupt += new NativeEventHandler(WiFiInterrupt_OnInterrupt);
try
{
byte[] in_initialise = { 0x15, 0x00 }; //initialisation
byte[] out_initialise = new byte[2];
SPI1.WriteRead(in_initialise, out_initialise);
if (out_initialise[1] != 0x58) //SUCCESSFUL
{
WiFiReset.Write(false);
Thread.Sleep(1);
WiFiReset.Write(true);
SPI1.WriteRead(in_initialise, out_initialise);
}
if (out_initialise[1] == 0x58)
{
Debug.Print("WiFi is Initialised.");
WiFiInterrupt.ClearInterrupt();
intFlag = false;
byte[] in_bandStart = { 0x7c, 0x04, 0x10, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00 }; //Band
byte[] out_bandStart = new byte[20];
SPI1.WriteRead(in_bandStart, out_bandStart);
if (out_bandStart[19] == 0x58) //SUCCESSFUL
{
//Debug.Print("WiFi established Band Command Start.");
while (intFlag == false && delay < maxDelay)
{
++delay; //waiting for interrupt
SPI1.WriteRead(tx_data, rx_data);
if (rx_data[0] == 0x55)
break;
Thread.Sleep(1);
}
if (delay != maxDelay)
{
*****************************************************************************************************
static void WiFiInterrupt_OnInterrupt(uint data1, uint data2, DateTime time)
{
byte[] in_intStart = { 0x5c, 0x00, 0x10, 0x00 }; //Band Start
byte[] out_intStart = new byte[4];
SPI1.WriteRead(in_intStart, out_intStart);
intFlag = true;
intTime = time;
}
At the point that the first interrupt is due, I have already received 0x58 several times confirming receipt (see "Waiting for interrupt").
Band Command Start
Send : 7c Recv : 00
Send : 04 Recv : 58
Send : 10 Recv : 58
Send : 00 Recv : 58
Send : 02 Recv : 58
Send : 18 Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 04 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Wait for interrupt
Interrupt received, Do master read
Send : 5c Recv : 00
Send : 00 Recv : 58
Send : 10 Recv : 58
Send : 00 Recv : 58
wait for start token
Send : Dummy 00 Recv : 58
Send : Dummy 00 Recv : 58
Send : Dummy 00 Recv : 55
Read descriptor is
Send : Dummy 00 Recv : 00
Send : Dummy 00 Recv : 97 .........Band Success Response
Send : Dummy 00 Recv : 00
Send : Dummy 00 Recv : 00
Send : Dummy 00 Recv : 00
Send : Dummy 00 Recv : 00
Send : Dummy 00 Recv : 00
Send : Dummy 00 Recv : 55
Send : Dummy 00 Recv : 88
Send : Dummy 00 Recv : 01
Send : Dummy 00 Recv : 00
Send : Dummy 00 Recv : 00
Send : Dummy 00 Recv : d1
Send : Dummy 00 Recv : 27
Send : Dummy 00 Recv : 04
Send : Dummy 00 Recv : 00
Band Response =97 Status=00
--------------------------------------------
Init Start
Send : 7c Recv : 80
Send : 04 Recv : 58
Send : 10 Recv : 58
Send : 00 Recv : 58
Send : 00 Recv : 58
Send : 10 Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Send : 00 Dummy Recv : 58
Any comments would be much appreciated.
Kevin.

This behavior is correct. Your module is generating INT based only on level transition with no edge (blue line on image). EMX set as InterruptEdgeLow/Both/High is expecting only specific (or nonspecific if both edge) edge transition and because only level has changed (without edge), INT is not generated.
This image is not so accurate (transisiton on blue line probably is taking longer in your case) but shows the difference.

The redpine module is level triggered.
You should be able to configure your interrupt handler to detect a rising edge, which will be raised when you transition from low to high.
However, that particular device can leave the interrupt line high when there is further data to service. So you'll need to poll for the interrupt line at the end of your ISR, and only acknowledge the interrupt if you discover that it's low.
Doing so allows your interrupt to trigger again.

Related

Socket error on client <>, disconnecting with Paho MQTT-SN Gateway and ESP8266 CLient

I'm trying to test MQTT-SN.
I'm using Mosquitto Broker, Paho MQTT-SN Gateway and this library (https://github.com/S3ler/arduino-mqtt-sn-client) for the clients.
I'm using an esp8266 as a client.
With this client, I can connect, subscribe, receive from subscribed topics but I cant publish into topics
memset(buffer, 0x0, buffer_length);
mqttSnClient.publish(buffer, publishTopicName , qos);
Every time I try to publish with this client, Mosquitto gives me
Socket error on client <clientid>, disconnecting
And my client disconnects from the Broker.
Any clues?
EDIT1
Client Code
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include "WiFiUdpSocket.h"
#include "MqttSnClient.h"
#include <NTPClient.h>
const char* ssid = "example";
const char* password = "example1";
long utcOffsetInSeconds = -10800;
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
#define buffer_length 10
char buffer[buffer_length + 1];
uint16_t buffer_pos = 0;
IPAddress gatewayIPAddress(192, 168, 0, 106);
uint16_t localUdpPort = 10000;
WiFiUDP udp;
WiFiUdpSocket wiFiUdpSocket(udp, localUdpPort);
MqttSnClient<WiFiUdpSocket> mqttSnClient(wiFiUdpSocket);
const char* clientId = "hamilton12";
char* subscribeTopicName = "ESP8266/123";
char* publishTopicName = "ESP8266/123";
int8_t qos = 1;
void mqttsn_callback(char *topic, uint8_t *payload, uint16_t length, bool retain) {
timeClient.update();
Serial.print("Received - Topic: ");
Serial.print(topic);
Serial.print(" Payload: ");
for (uint16_t i = 0; i < length; i++) {
char c = (char) * (payload + i);
Serial.print(c);
}
Serial.print(" Lenght: ");
Serial.print(length);
Serial.print(" Received Timestamp milliseconds: ");
Serial.print(timeClient.getHours());
Serial.print(":");
Serial.print(timeClient.getMinutes());
Serial.print(":");
Serial.println(timeClient.getSeconds());
}
void setup() {
Serial.begin(115200);
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
/* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default,
would try to act as both a client and an access-point and could cause
network-issues with your other WiFi-devices on your WiFi-network. */
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.print("Starting MqttSnClient - ");
mqttSnClient.setCallback(mqttsn_callback);
if (!mqttSnClient.begin()) {
Serial.print("Could not initialize MQTT-SN Client ");
while (true) {
Serial.println(".");
delay(1000);
}
}
Serial.println(" ready!");
}
void convertIPAddressAndPortToDeviceAddress(IPAddress& source, uint16_t port, device_address& target) {
// IPAdress 0 - 3 bytes
target.bytes[0] = source[0];
target.bytes[1] = source[1];
target.bytes[2] = source[2];
target.bytes[3] = source[3];
// Port 4 - 5 bytes
target.bytes[4] = port >> 8;
target.bytes[5] = (uint8_t) port ;
}
void loop() {
if (!mqttSnClient.is_mqttsn_connected()) {
#if defined(gatewayHostAddress)
IPAddress gatewayIPAddress;
if (!WiFi.hostByName(gatewayHostAddress, gatewayIPAddress, 20000)) {
Serial.println("Could not lookup MQTT-SN Gateway.");
return;
}
#endif
device_address gateway_device_address;
convertIPAddressAndPortToDeviceAddress(gatewayIPAddress, localUdpPort, gateway_device_address);
Serial.print("MQTT-SN Gateway device_address: ");
printDeviceAddress(&gateway_device_address);
if (!mqttSnClient.connect(&gateway_device_address, clientId, 180) ) {
Serial.println("Could not connect MQTT-SN Client.");
delay(1000);
return;
}
Serial.println("MQTT-SN Client connected.");
//mqttSnClient.set_mqttsn_connected();
if (!mqttSnClient.subscribe(subscribeTopicName, qos)){
Serial.println("Cant subscribe");
}
Serial.println("Subscribed");
}
//It never enters this IF
if (Serial.available() > 0) {
buffer[buffer_pos++] = Serial.read();
if (buffer[buffer_pos - 1] == '\n') {
// only qos -1, 0, 1 are supported
if (!mqttSnClient.publish(buffer, publishTopicName , qos)) {
Serial.println("Could not publish");
}
Serial.println("Published");
memset(buffer, 0x0, buffer_length);
buffer_pos = 0;
}
}
//Uncommenting this line will give socket error
//mqttSnClient.publish(buffer, publishTopicName , qos);
mqttSnClient.loop();
}
etc/mosquitto/mosquitto.conf
pid_file /var/run/mosquitto.pid
persistence true
persistence_location /var/lib/mosquitto/
log_dest file /var/log/mosquitto/mosquitto.log
#include_dir /etc/mosquitto/conf.d
connection_messages true
log_timestamp true
log_dest stderr
log_type error
log_type warning
log_type debug
allow_anonymous true
gateway.conf
BrokerName=192.168.0.106
BrokerPortNo=1883
BrokerSecurePortNo=8883
#
# When AggregatingGateway=YES or ClientAuthentication=YES,
# All clients must be specified by the ClientList File
#
ClientAuthentication=NO
AggregatingGateway=NO
QoS-1=NO
Forwarder=NO
#ClientsList=/path/to/your_clients.conf
PredefinedTopic=NO
#PredefinedTopicList=/path/to/your_predefinedTopic.conf
#RootCAfile=/etc/ssl/certs/ca-certificates.crt
#RootCApath=/etc/ssl/certs/
#CertsFile=/path/to/certKey.pem
#PrivateKey=/path/to/privateKey.pem
GatewayID=1
GatewayName=PahoGateway-01
KeepAlive=900
#LoginID=your_ID
#Password=your_Password
# UDP
GatewayPortNo=10000
MulticastIP=225.1.1.1
MulticastPortNo=1884
# UDP6
GatewayUDP6Bind=FFFF:FFFE::1
GatewayUDP6Port=10000
GatewayUDP6Broadcast=FF02::1
GatewayUDP6If=wpan0
# XBee
Baudrate=38400
SerialDevice=/dev/ttyUSB0
ApiMode=2
# LOG
ShearedMemory=NO;
EDIT2
Terminal running mosquitto
hamilton#hamilton-note:~$ mosquitto
1574806892: mosquitto version 1.4.15 (build date Tue, 18 Jun 2019 11:42:22 -0300) starting
1574806892: Using default config.
1574806892: Opening ipv4 listen socket on port 1883.
1574806892: Opening ipv6 listen socket on port 1883.
1574806900: New connection from 192.168.0.106 on port 1883.
1574806900: New client connected from 192.168.0.106 as hamilton123 (c1, k46080).
1574806900: Socket error on client hamilton123, disconnecting.
^C1574806911: mosquitto version 1.4.15 terminating
Terminal running Paho Gateway
hamilton#hamilton-note:~/Downloads$ ./MQTT-SNGateway
***************************************************************************
* MQTT-SN Transparent Gateway
* Part of Project Paho in Eclipse
* (http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt-sn.embedded-c.git/)
*
* Author : Tomoaki YAMAGUCHI
* Version: 1.3.1
***************************************************************************
20191126 192134.372 PahoGateway-01 has been started.
ConfigFile: ./gateway.conf
PreDefFile: ./predefinedTopic.conf
SensorN/W: UDP Multicast 225.1.1.1:1884 Gateway Port 10000
Broker: 192.168.0.106 : 1883, 8883
RootCApath: (null)
RootCAfile: (null)
CertKey: (null)
PrivateKey: (null)
20191126 192140.660 CONNECT <--- hamilton123 12 04 04 01 B4 00 68 61 6D 69 6C 74 6F 6E 31 32 33 00
20191126 192140.660 CONNECT ===> hamilton123 10 17 00 04 4D 51 54 54 04 02 B4 00 00 0B 68 61 6D 69 6C 74 6F 6E 31 32 33
20191126 192140.874 CONNACK <=== hamilton123 20 02 00 00
20191126 192140.874 CONNACK ---> hamilton123 03 05 00
20191126 192140.879 SUBSCRIBE 0200 <--- hamilton123 11 12 20 02 00 45 53 50 38 32 36 36 2F 31 32 33 00
20191126 192140.879 SUBSCRIBE 0200 ===> hamilton123 82 10 02 00 00 0B 45 53 50 38 32 36 36 2F 31 32 33 01
20191126 192140.879 SUBACK 0200 <=== hamilton123 90 03 02 00 01
20191126 192140.879 SUBACK 0200 ---> hamilton123 08 13 20 00 01 02 00 00
20191126 192140.883 PUBLISH 0300 <--- hamilton123 08 0C 22 00 01 03 00 00
20191126 192140.884 PUBLISH 0300 ===> hamilton123 32 07 00 02 00 01 03 00 00
^C20191126 192149.215 BrokerSendTask stopped.
20191126 192149.215 PacketHandleTask stopped.
20191126 192149.215 ClientSendTask stopped.
20191126 192149.386 BrokerRecvTask stopped.
20191126 192150.158 ClientRecvTask stopped.
20191126 192150.215 MQTT-SN Gateway stoped
Thank you for the help Dalton Cézane.
But I found the problem in an open issue in the client's library:
Having trouble with your example WiFiUdpMqttSnClient program in that
it does not successfully publish the test messages. I'm using
paho-mqtt-sn gateway.
I'm bashing around in the dark a bit but I think this is because it
publishes the messages with the flag TopicIdType set to 2. I think it
should be zero (normal) because it's not pre-registered nor is it a
short topic.
In file MqttSnClient.h line 216 the call to send_publish has
short_topic set to true. But that's not all; in file mqttsn_messages.h
around line 215 if short_topic flag is false it sets the flag to
predefined. I've removed the latter 'else' clause so the flag is set
to zero and I can now publish successfully.
I suspect my hack is not a complete solution but I hope it helps you
resolve this issue.
This comment was made by #nottledim, big thanks!
Now i can publish without a problem using my esp8266.
Just leaving here if anyone has this problem.
link to the issue: https://github.com/S3ler/arduino-mqtt-sn-client/issues/3

How do loop over the search results for a byte string and offset the resultant pointer (in WinDbg)?

I'm attempting to search for an arbitrarily long byte string in WinDbg and print out the address if an integer in the vicinity meets some criteria.
Pseudo-register $t0 contains the starting address I want to search.
Here's something that, based on the Windows docs, maybe could work (though it clearly doesn't).
.foreach (place { s -[1] #$t0 L?30000 00 00 00 00 00 20 00 00 }) { .if ( (place +0x8) <= 0x1388) { .printf "0x%x\n", place } }
Search
First, the search command doesn't quite work correctly. I only want the address of the match (not the data).
s -[1] #$t0 L?30000 00 00 00 00 00 20 00 00
The docs say that the 1 flag will only return the address. When I issue that command, WinDbg replies
^ Syntax error in 's -1 #$t0 L?30000 00 00 00 00 00 20 00 00 '
If I leave out the -1, it finds two matches.
What am I doing wrong here?
Condition
I don't think the condition is behaving the way I want. I want to look at the third dword starting at place, i.e. place+8, and verify that it's smaller than 5000 (decimal). The .if inside the .foreach isn't printing a meaningful value for place (i.e. the address returned from the search). I think it's dereferencing place first and comparing the value of that integer to 5000. How do I look at the value of, say, *(int*)(place+8)?
Documentation?
The docs are not helping me very much. They only have sparse examples, none of which correspond to what I need.
Is there better documentation somewhere besides MS's Hardware Dev Center?
you can start writing JavaScript for a more legible way of scripting
old way
0:000> s -b vect l?0x1000 4d
00007ff7`8aaa0000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ..............
00007ff7`8aaa00d4 4d 90 80 d2 df f9 82 d3-4d 90 80 d2 52 69 63 68 M.......M...Rich
00007ff7`8aaa00dc 4d 90 80 d2 52 69 63 68-4c 90 80 d2 00 00 00 00 M...RichL.......
0:000> s -[1]b vect l?0x1000 4d
0x00007ff7`8aaa0000
0x00007ff7`8aaa00d4
0x00007ff7`8aaa00dc
using javascript
function search(addr,len)
{
var index = []
var mem = host.memory.readMemoryValues(addr,len)
for(var i = 0; i < len; i++)
{
if(mem[i] == 0x4d)
{
index.push(addr+i)
}
}
return index
}
executed will return address like which you can manipulate further
0:000> dx -r1 #$scriptContents.search(0x00007ff78aaa0000,1000)
#$scriptContents.search(0x00007ff78aaa0000,1000) : 140701160046592,140701160046804,140701160046812
length : 0x3
[0x0] : 0x7ff78aaa0000
[0x1] : 0x7ff78aaa00d4
[0x2] : 0x7ff78aaa00dc
improving the script a little to find something based on first result
we will try to find the index of Rich string that follows the character 'M'
modified script
function search(addr,len)
{
var index = []
var Rich = []
var result = []
var mem = host.memory.readMemoryValues(addr,len)
for(var i = 0; i < len; i++)
{
if(mem[i] == 0x4d)
{
index.push(addr+i)
var temp = host.memory.readMemoryValues(addr+i+4,1,4)
host.diagnostics.debugLog(temp +"\t")
if(temp == 0x68636952)
{
Rich.push(addr+i)
}
}
}
result.push(index)
result.push(Rich)
return result
}
result only the third occurance of char "M" is followed by Rich string
0:000> dx -r2 #$scriptContents.search(0x00007ff78aaa0000,1000)
3 3548576223 1751345490 #$scriptContents.search(0x00007ff78aaa0000,1000) : 140701160046592,140701160046804,140701160046812,140701160046812
length : 0x2
[0x0] : 140701160046592,140701160046804,140701160046812
length : 0x3
[0x0] : 0x7ff78aaa0000
[0x1] : 0x7ff78aaa00d4
[0x2] : 0x7ff78aaa00dc
[0x1] : 140701160046812
length : 0x1
[0x0] : 0x7ff78aaa00dc
0:000> s -b vect l?0x1000 4d
00007ff7`8aaa0000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ..............
00007ff7`8aaa00d4 4d 90 80 d2 df f9 82 d3-4d 90 80 d2 52 69 63 68 M.......M...Rich
00007ff7`8aaa00dc 4d 90 80 d2 52 69 63 68-4c 90 80 d2 00 00 00 00 M...RichL.......
load the extensension jsprovider.dll .load jsprovider
write a script say foo.js
load the script .scriptload ...\path\foo.js
execute any functions inside the js you wrote with dx #$scriptContents.myfunc(myargs)
see below using cdb just for ease of copy paste windbg works just as is
F:\>type mojo.js
function hola_mojo ()
{
host.diagnostics.debugLog("hola mojo this is javascript \n")
}
F:\>cdb -c ".load jsprovider;.scriptload .\mojo.js;dx #$scriptContents.hola_mojo();q" cdb | f:\usr\bin\grep.exe -A 6 -i reading
0:000> cdb: Reading initial command '.load jsprovider;.scriptload .\mojo.js;dx #$scriptContents.hola_mojo();q'
JavaScript script successfully loaded from 'F:\mojo.js'
hola mojo this is javascript
#$scriptContents.hola_mojo()
quit:
If I read this part of the documentation
s [-[[Flags]Type]] Range Pattern
correctly, you cannot leave out Type when specifying flags. That's because the flags are inside two square brackets. Otherwise it would have been noted as s [-[Flags][Type]] Range Pattern.
Considering this, the example works:
0:000> .dvalloc 2000
Allocated 2000 bytes starting at 00ba0000
0:000> eb 00ba0000 01 02 03 04 05 06 07 08 09
0:000> eb 00ba1000 01 02 03 04 05 06 07 08 09
0:000> s -[1]b 00ba0000 L?2000 01 02 03 04 05 06 07 08
0x00ba0000
0x00ba1000
Also note that you'll have a hidden bug for the use of place: it should be ${place}. By default, that will work with the address (line break for readability on SO):
0:000> .foreach (place {s -[1]b 00ba0000 L?2000 01 02 03 04 05 06 07 08 })
{ .if ( (${place} +0x8) < 0xba1000) { .printf "0x%x\n", ${place} } }
0xba0000
In order to read a DWord from that address, use the dwo() MASM oerator (line break for readability on SO):
0:000> .foreach (place {s -[1]b 00ba0000 L?2000 01 02 03 04 05 06 07 08 })
{ .if ( (dwo(${place} +0x8)) < 0xba1000)
{ .printf "0x%x = 0x%x\n", ${place}, dwo(${place}+8) } }
0xba0000 = 0x9
0xba1000 = 0x9

Create PCAP file from values in a database

I have a database filled with a lot of logged IPV4 messages. It is used to get queries like: "give me all messages from MacAddress ... that were logged in the period ... to ... that have ..."
Some queries will result in a huge amount of logged messages. Therefore we decided to make a PCAP file if such a request was made.
"Please create a PCAP file containing all logged messages from your
database that ..."
So upon request, my service should fetch the requested data from the database (in pages) and create a PCAP file filled with the data fetched from the database. Later callers can ask for a read-only OWIN stream to this file
The service can create such a file. The problem is that it is not recognized as a proper WireShark file.
I've read Libcap File Format. Whenever I have to create a file filled with LoggedMessages I fill a binary file as follows.
Global Header
Per logged message:
A packet header
Packet data with:
Ethernet Frame: Destination Mac, Source Mac, EtherType (0x800)
IPV4 header
Logged Data
Wireshark starts complaining about the file when it attempts to read the Ethertype. It says this is a Length. Definition of Ethernet Frame with EtherType
So below I show the start of my file. Hexadecimal format per byte + my interpretation of it. After that the comments from wireshark
The created stream starts with the Global Header: a 32 bytes structure. First the hexadecimal values then the interpretation:
=== Global Header ====
D4 C3 B2 A1 02 00 04 00
00 00 00 00 00 00 00 00
FF FF 00 00 01 00 00 00
Magic number A1B2C3D4 (Original Time Precision)
Version: 2 - 4
ThisZone 0
sigFigs 0
snapLen 0000FFFF
datalinkType 1
Note that the magic number has the LSB first, indicating that every multi-byte number will have the least significant byte first. So a 2 byte value of 0x1234 will have in memory first 34 then 12.
After that the Packets should come. Every time one Packet Header, followed by one Packet Data
=== Packet header ===
09 89 58 5A C8 85 0B 00
6B 00 00 00 6B 00 00 00
Timestamp: 1515751689.7551446 (usec precision)
Number of saved bytes (incl_len) 107 bytes (0x006b)
Actual packet length (orig_len) 107 bytes (0x006b)
=== Packet Data ===
CF 31 59 D3 E7 98 53 39 - 17 F0 A9 9C 00 08 45 00
5D 00 00 00 00 00 FF 00 - E0 0D 8A 84 77 44 E0 2B
9C FB 4D 43 D5 8A 00 00 - 00 00 41 41 41 41 41 41
41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41
// etc, until total 107 bytes
The packet data consists of a Mac Header, IPV4 header and a couple of 0x41 as data
=== Mac Header ===
Destination Mac: CF:31:59:D3:E7:98
Source Mac: 53:39:17:F0:A9:9C
Ether type: 0800
Note that the magic number showed that every multi-byte number has the LSB first, so the two bytes 00 08 will have a 16-bit meaning of 0x0800
If you look at the PCAP file interpretation I show below, then the problem starts here: the Ether Type is not interpreted as Ether Type, but as length.
After remark in one of the answers, I tried to reverse the two byte ether type from 00 08 into 08 00 (MSB first), but that made the problems worse.
=== IPV4 header ===
- 45 00 5D 00
- 00 00 00 00
- FF 00 E0 0D
- 8A 84 77 44
- E0 2B 9C FB
Specification of the IPV4 header structure
DWORD 0
- bits 00..04: version; bits 04..07 IP Header Length: 04 05
- bits 08..13 DSCP; bits 14..15 ECN: 00
- bits 16..31 Total Length (header + Payload): 93 (005D)
DWORD 1
- bits 00..15 Identification: 0000
- bits 16..18 Flags; bits 19..31 offset: 0000
DWORD 2
- bits 00..07 Time to Live FF
- bits 08..15 Protocol; used protocol 00
- bits 16..31 Header Checksum 3552 (0DE0)
DWORD 3 and 4
Source IP: 138.132.119.68
Destination IP: 224.43.156.251
Bacause wireshark complains about checksum, I verify as follows:
Verify checksum:
Header: 0045 005D 0000 0000 00FF 0DE0 848A 4477 2BE0 FB9C
69 + 93 + 0 + 0 + 255 + 3552 + 33930 + 17527 + 11232 + 64412 = 131070 (01FFFE)
0001 + FFFE = FFFF
1's complement: 0000 (checksum ok)
This is what WireShark (version 2.4.4) makes of it:
The following seems normal:
Frame 1: 107 bytes on wire (856 bits), 107 bytes captured (856 bits)
Encapsulation type: Ethernet (1)
Arrival Time: Jan 12, 2018 11:08:09.755144000 W. Europe Standard Time
[Time shift for this packet: 0.000000000 seconds]
Epoch Time: 1515751689.755144000 seconds
[Time delta from previous captured frame: 0.000000000 seconds]
[Time delta from previous displayed frame: 0.000000000 seconds]
[Time since reference or first frame: 0.000000000 seconds]
Frame Number: 1
Frame Length: 107 bytes (856 bits)
Capture Length: 107 bytes (856 bits)
[Frame is marked: False]
[Frame is ignored: False]
[Protocols in frame: eth:llc:data]
[Coloring Rule Name: Checksum Errors]
[Coloring Rule String [truncated]: eth.fcs.status=="Bad" ||
ip.checksum.status=="Bad" || tcp.checksum.status=="Bad" ||
udp.checksum.status=="Bad" || sctp.checksum.status=="Bad" ||
mstp.checksum.status=="Bad" || cdp.checksum.status=="Bad" ||]
Here comes the first problem: EtherType is interpreted as Length
IEEE 802.3 Ethernet
Destination: cf:31:59:d3:e7:98 (cf:31:59:d3:e7:98)
Source: 53:39:17:f0:a9:9c (53:39:17:f0:a9:9c)
Length: 8
Padding: ff00e00d8a847744e02b9cfb4d43d58a0000000041414141...
Trailer: 414141414141414141414141414141414141414141414141...
Frame check sequence: 0x41414141 incorrect, should be 0xe19cae36
[FCS Status: Bad]
After the length, which I meant as an EtherType, comes a lot of padding, instead of interpretation of my 5 DWORDs.
The link to the Ethernet Frame in wikipedia I showed says:
The EtherType field is two octets long and it can be used for two
different purposes. Values of 1500 and below mean that it is used to
indicate the size of the payload in octets, while values of 1536 and
above indicate that it is used as an EtherType, to indicate which
protocol is encapsulated in the payload of the frame.
My value if 0x0800 = 2048. This certainly is above 1536
For example, an EtherType value of 0x0800 signals that the frame
contains an IPv4 datagram.
If value 0x0800 the incorrect value? Or is my error somewhere else?
Looks like your ethertype has the wrong byte order. It should be:
=== Packet Data ===
CF 31 59 D3 E7 98 53 39 - 17 F0 A9 9C 08 00 XX XX

Problems with sending UDP packets (milight, limitlessled)

I trying to write a menubar app to get control over my lights via Mac.
I'm using the system of milight (limitless, easybulbs...).
They have an open system were you can send commands via UDP.
I'm able to control my lights via python-limitless library in python, so I know the networking thing such as IP and port is right.
So I think I do anything wrong with this UDP stuff I never worked with.
I'm trying to use SwiftSocket library to send my commands but nothing happens, I've been trying it since 2 days.
Here ist what I'm trying:
let host = "192.168.2.102"
let port = 5987
var client: UDPClient!
#IBAction func lightOn(_ sender: NSButton) {
let bridgeon: [UInt8] = [0x31, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x01]
let rgbwon: [UInt8] = [0x31, 0x00, 0x00, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0]
print("Licht an")
print(client.send(data: bridgeon))
sleep(1)
print(client.send(data: rgbwon))
sleep(1)
}
#IBAction func lightOff(_ sender: NSButton) {
print("Licht aus")
}
override func viewDidLoad() {
super.viewDidLoad()
client = UDPClient(address: host, port: Int32(port))
}
When I compare this with the complexity of the pythonlibrary I'm sure I forget something important. I haven't worked with networks yet so be lenient with me.
thanks and greetings.
I'm a bit late, but I hope it can help you :
Before sending your lighton request you have to send a first request to get, the wifi bridge session. You also need to compute what Milight called the "checksum" based on your request.
You also make sure about what kind of bulb you have, is it WW bulb or CW? I was stuck for severals days because I was sending wrong request..
I made an implementation, It's in php but you can use it same way in Objective-C.
Check it out : https://github.com/winosaure/MilightAPI
UPDATE :
According to limitlessled "documentation" (http://www.limitlessled.com/dev/) this is how a request is composed :
UDP Hex Send Format: 80 00 00 00 11 {WifiBridgeSessionID1}
{WifiBridgeSessionID2} 00 {SequenceNumber} 00 {COMMAND} {ZONE NUMBER}
00 {Checksum}
This is why you must get wifibridge session first then you need to calculate the checksum.
Let me take one example about how to turn on the light.
The documentation says that :
31 00 00 08 04 01 00 00 00 = Light ON
31 00 00 08 04 01 00 00 00 refer to {COMMAND} above.
So far the full request must be :
80 00 00 00 11 {WifiBridgeSessionID1} {WifiBridgeSessionID2} 00 {SequenceNumber} 00 31 00 00 08 04 01 00 00 00 {ZONE NUMBER} 00 {Checksum}
Now let's get the Wifibridge session. The documention says :
to get the WifiBridgeSessionID1 and WifiBridgeSessionID2 send this
command UDP.
SEND hex bytes: 20 00 00 00 16 02 62 3A D5 ED A3 01 AE 08
2D 46 61 41 A7 F6 DC AF (D3 E6) 00 00 1E <-- Send this to the ip
address of the wifi bridge v6
That's why I'm doing this:
private function getWifiBridgeSession()
{
$command = array (
0x20,0x00, 0x00,
0x00, 0x16, 0x02,
0x62, 0x3A, 0xD5,
0xED, 0xA3, 0x01,
0xAE, 0x08, 0x2D,
0x46, 0x61, 0x41,
0xA7, 0xF6, 0xDC,
0xAF, 0xD3, 0xE6,
0x00, 0x00, 0x1E);
return $this->sendCommand($command);
}
Once you send a UDP request with this command, you will get a result.
The Wifi Bridge session1 refers to the 20th byte of the response and WifiBridge Session2 will refer to the 21th byte response (Don't forget that we start to count from 0, so you must take something like "response[19]" and "response[20]").
Let's say, after sending this request I get this response :
28 00 00 00 11 00 02 AC CF 23 F5 7A D4 69 F0 3C 23 00 01 05 00
So my "WifiBridgesession1" is 0x05 and "Wifibridgesession2" is 0x00
So now our request to "turn on" the light is :
80 00 00 00 11 0x05 0x00 00 {SequenceNumber} 00 31 00 00 08 04 01 00 00 00 {ZONE NUMBER} 00 {Checksum}
So now we need to find out {SequenceNumber} {Zone Number} and {Checksum}
What is a "Sequence Number"?
The doc says :
Sequential byte just helps with keeping commands in the correct order,
and it helps to ignore duplicate packets already received. increment
this byte for each new command by 1.
So put what you want and increase this value to 1 for each request. (Personnally I always send 0x01).
"Zone number" refers to which zone you synchronized your light.
Valid List for {ZONE NUMBER} 0x00 All 0x01 Zone1 0x02 Zone2 0x03
Zone3 0x04 Zone4
Let's say, our "zone" is 0x01.
Almost done. we just need now to calculate the "checksum".
The doc says :
take the 9 bytes of the command, and 1 byte of the zone, and add the 0
= the checksum = (checksum & 0xFF) e.g. SUM((31 00 00 08 04 01 00 00 00)(command) 01(zone) 00) = 3F(chksum)
So the checksum for our command is :
31+00+00+08+04+01+00+00+00+01+00 = 0x54
I add all byte of the command (turn on) + 0x01 for the zone + 0x00
So now we have everything and the full request to turn on the light is :
80 00 00 00 11 05 00 00 01 00 31 00 00 08 04 01 00 00 00 01 00 54
That's it.
Note : Do not just copy and paste the request, I calculated the value based on example, the request to turn on the light will change each time, based on what you will calculate.
Maybe you got noticed that I wrote "00 31 00 00 08 04 01 00 00 00" to do the "turn on" command, this will work only for CW bulb. The doc does not specify that...
The same Command for WW bulb is 00 31 00 00 07 03 01 00 00 00
So the full command for WW bulb will be :
80 00 00 00 11 05 00 00 01 00 31 00 00 07 03 01 00 00 00 01 00 54
What is the difference between CW and WW bulb?
I can tell that CW refers to "Cold White" and WW to "Warm White". But as I am not an expert in "led bulb" I cannot explain more, I don't know why we need to write a different request for both, either.
Anyway I wish I was clear enough.
Let me know how things are working.

What is wrong with this .ico file that has a .png image inside it?

I based the file on https://en.wikipedia.org/wiki/ICO_(file_format) and https://www.w3.org/TR/PNG/. I will translate the .ico file from how it looks in my hex editor into some kind of pseudo-binary (the order of the bytes are as written out):
ICONDIR{
uint16_t idReserved : 00 00
uint16_t idType : 00 01
uint16_t idCount : 00 01
ICONDIRENTRY{
uint8_t bWidth : 01
uint8_t bHeight : 01
uint8_t bColorCount : 00
uint8_t bReserved : 00
uint16_t wPlanes : 00 00
uint16_t wBitCount : 00 20
uint32_t dwBytesInRes : 00 00 00 49
uint32_t dwImageOffset : 00 00 00 16
}
}
PNG{
uint8_t PNGSignature[8] : 89 50 4E 47 0D 0A 1A 0A
IHDR{
uint32_t Length : 00 00 00 0D
uint8_t ChunkType[4] : 49 48 44 52 //IHDR
uint32_t Width : 00 00 00 01
uint32_t Height : 00 00 00 01
uint8_t BitDepth : 08 //8 bits
uint8_t ColourType : 06 //RGBA
uint8_t CompressionMethod : 00
uint8_t FilterMethod : 00
uint8_t InterlaceMethod : 00
uint32_t CRC32 : 1F 15 C4 89 //CRC32 of bits [ChunkType,...,InterlaceMethod]
}
IDAT{
uint32_t Length : 00 00 00 10
uint8_t ChunkType[4] : 49 44 41 54 //IDAT
ZLIB{
(CMF.CINFO = 0000,CMF.CM = 1000) : 08
(FLG.FLEVEL = 10 /*Slowest Algorithm*/
,FLG.FDICT = 0 /* No dictionary */
,FLG.FCHECK = 11001 /* 0000100010011001 = 2201 = 71 x 31 */) : 99
DEFLATE{
(BFINAL = 1 /* Last block */
,BTYPE = 00 /* No compression */
,<No compression ignored bytes = 00000>) : 80
uint16_t LEN : 00 05
uint16_t NLEN : FF FA
LITERAL_DATA_SCANLINE{
uint8_t FilterTypeByte : 00 // No filtering
PIXEL{
uint8_t R : FF
uint8_t G : 00
uint8_t B : 00
uint8_t A : FF
}
}
}
uint32_t ADLER32 : 00 AB 00 A2
}
uint32_t CRC32 : 02 EA 6B 91 //CRC32 of bits [ChunkType,ZLIB]
}
IEND{
uint32_t Length : 00 00 00 00
uint8_t ChunkType[4] : 49 45 4E 44
uint32_t CRC32 : AE 42 60 82 //CRC32 of [ChunkType]
}
}
PNG image (magnified to size 100x100):
Since the PNG can be displayed I guess there is some documentation I have not found/misinterpreted. Please point to the error if you see it!
I had missed the little-endian part... Correct version of the ICO part is:
ICONDIR{
uint16_t idReserved : 00 00
uint16_t idType : 01 00
uint16_t idCount : 01 00
ICONDIRENTRY{
uint8_t bWidth : 01
uint8_t bHeight : 01
uint8_t bColorCount : 00
uint8_t bReserved : 00
uint16_t wPlanes : 00 00
uint16_t wBitCount : 20 00
uint32_t dwBytesInRes : 49 00 00 00
uint32_t dwImageOffset : 16 00 00 00
}
}