Playing on the frontier https://loune.net A log of random stuff that interests me. Sun, 21 Jan 2024 10:09:44 +0000 en-AU hourly 1 Why can’t I create a new socket or bind to a new port in my new app on macOS? https://loune.net/2024/01/why-cant-i-create-a-new-socket-bind-to-a-new-port-in-my-new-app-on-macos/ https://loune.net/2024/01/why-cant-i-create-a-new-socket-bind-to-a-new-port-in-my-new-app-on-macos/#respond Sun, 21 Jan 2024 10:09:03 +0000 https://loune.net/?p=619 I’m building a new app on macOS. It’s the first time I’m building in Swift (and SwiftUI) and the latest Xcode (15.2). My app requires me to use UPnP to connect to a smart device on the network. I decided to use SwiftUpnp. However, I quickly ran into a problem. The library can’t start a HTTP listener, which is a prerequisite to starting service discovery. The error was a cryptic “Couldn’t start http server on port 0. The operation couldn’t be completed. (Swifter.SocketError error 2.)”. Copilot and ChatGPT only gave a generic answer regarding not using 0 as a port. Looking deeper into the code, SwiftUPnP tries to find a free port, falling back to 0 if it fails. Something has gone wrong since there are a lot of free ports on my machine. It uses Darwin.bind to test if a port is free, however the call is always returning -1, which I guess means the port is not free. Searching up and down the Google didn’t yield much useful information.

Is it because the app is not signed? I’ve been compiling the app as an unverified developer. I know that for iOS apps, your app needs to be signed with certain entitlements for greater access to device functionality. Do you now need to do the same for macOS?

It turns out that there is now a bunch of Sandbox options for apps, which by default doesn’t let you perform incoming or outgoing connections.

Ticking those boxes solved this issue. Hopefully this will help someone in the future!

]]>
https://loune.net/2024/01/why-cant-i-create-a-new-socket-bind-to-a-new-port-in-my-new-app-on-macos/feed/ 0
ext4 encryption, multiple filesystems and salt https://loune.net/2018/12/ext4-encryption-multiple-filesystems-and-salt/ https://loune.net/2018/12/ext4-encryption-multiple-filesystems-and-salt/#respond Mon, 03 Dec 2018 12:06:39 +0000 https://loune.net/?p=606 Recently, I started to play around with ext4 transparent encryption. Following basic instructions from Arch Linux wiki, it was really easy to get it up and running. However, when using it with two ext4 filesystems, things get a little more complicated.

How to get the ext4 filesystem salt?

Each encryption enabled ext4 filesystem has a randomised salt. Salt is added to your key to thwart rainbow table attacks, especially with weak passwords. The salt for an ext4 filesystem is stored in the superblock and can be obtained with the dumpe2fs command:

# sudo dumpe2fs /dev/sdb2 | grep Salt
Encryption PW Salt: d24c7f08-5092-4b3a-9180-6ed8244513e8

Which key descriptor corresponds with which filesystem?

When using e4crypt add_key, you will get a separate descriptor for each mounted ext4 encryption enabled filesystem for the same password, due to different filesystems having different salt. Unfortunately it doesn’t say which descriptor was generated from which FS. However, you can determine this by providing the salt (obtained in the previous step) manually to the e4crypt command:

$ /usr/sbin/e4crypt add_key -S d24c7f08-5092-4b3a-9180-6ed8244513e8
Enter passphrase (echo disabled):
Added key with descriptor [9b9cf8b934f6d7bc]

It is important to know which key descriptor corresponds with which filesystem as if you used a descriptor with salt from filesystem 1 on filesystem 2, the descriptor will only ever be there if you add_key while filesystem 1 is mounted. Worse yet, if you reformat filesystem 1 and lose the salt, your filesystem 2 data will be gone forever.

To be safe, when you have multiple mounted filesystems with encryption, I would recommend always providing the salt when add_key.

]]>
https://loune.net/2018/12/ext4-encryption-multiple-filesystems-and-salt/feed/ 0
Decoding the Oregon Scientific Remote Weather Temperature Sensor https://loune.net/2018/01/decoding-the-oregon-scientific-temperature-sensor/ https://loune.net/2018/01/decoding-the-oregon-scientific-temperature-sensor/#comments Sun, 28 Jan 2018 03:49:26 +0000 https://loune.net/?p=576 A while ago, I bought a set of Oregon Scientific weather station on special. The package came with the clock and temperature display unit (BAR283) and a remote temperature sensor (RTHR328N), which is normally put outside of the house. The remote sensor then regularly sends temperature and humidity wirelessly to the display indoors. It has been a dream of mine to tap into the temperature data sent over the air and log it in database. Fortunately, there are a few tutorials online (jeelabs instructables) online and blog posts of people who have done the exact thing successfully.

To receive the signal, you need a Amplitude-shift keying (ASK) 433.92MHz receiver. I bought the Aurel AC-RX2 on advice of one the blog posts, but in reality, there are probably better 433.92 receivers such as the RXB6 as documented here.

To get the best reception, you need an antenna. I used a 17.2cm wire for the antenna. The full wire up of the Arduino and AC-RX2 is shown below:

Breadboard diagram

Data is connected to Pin 2.

I downloaded the source code and loaded onto my Arduino, unfortunately, nothing came out of the console. Changing pins and rewiring didn’t yield anything useful – It just would not work. The source code was not straightforward to understand and it wasn’t like I could just add breakpoints and step through the code. That’s when I decided that I needed to start from scratch. Fortunately, the Oregon Scientific protocol is quite well documented here.

The first thing I decided to do was to make sure that data is actually coming through to the output pin. I attached a USB logic analyser and used PulseView to see if there were any data coming through. Sure enough there was, but there were a lot of data which meant nothing to me. Removing the antenna, that was a lot less data coming through, which proved that everything was hooked up correctly.

In the protocol, there were some samples of what the signal should look like. It was a Manchester encoded signal on a 1024Hz clock. The other consideration was that the sensor was not sending data all the time, but only at certain intervals. Know the exact moment that data was sent would be key to identifying the signal. Fortunately, there was a clue in the form of an LED that would blink.

The blink would come every 106 seconds and sure enough, I got a very distinct signal when it blinked. The pattern of the signal was definitely artificial and not random.

Oregon Scientific RF Signal

Decoding the Manchester encoded signal

The signal is in Manchester coding with a clock of 1kHz. This means that sampling the state every 1ms should give us a stream of bits of the transmission. Unfortunately this naive approach is error prone due to slight variations in sampling time and signal. If sampling becomes offset then errors will accumulate.

Oregon Scientific 1kHz signal

A better approach is to look at the timings of a the HIGH and LOWs and classifying each HIGH and LOW into short and long pulses. Because the signal is Manchester coded, the signal should oscillate between HIGH and LOW at least every 1ms. A long pulse should not be longer than 1ms. and a short pulse should be around 0.5ms.

However, as mentioned above, these timings can have slight variations. Therefore, we should allow for some leeway for long and short pulses.

Now that we have identified HIGHs and LOWs, long and short pulse, we need to convert them into a bit stream.

The logic I came up with is quite simple:

  • A HIGH long pulse is basically a 0 followed by 1
  • A LOW long pulse then a HIGH short pulse is 0
  • A LOW short pulse then a HIGH short pulse should repeat the previous bit

The binary representation looks something like this:

01010101010101010101010101100110011001100110100101011001010101101001101001100110010101011001101010101010011010101001011010101010101010010110100110100101100101011

Oregon Scientific Protocol

Oregon Scientific Protocol 2 actually sends each bit in pairs, the inverse of the bit and then the actual bit. We only need to look at every second bit. To identify a valid signal, we look for the preamble and the sync, which is 16 1 bits followed by 0101. After finding this pattern, we then convert the rest of the bitstream into BCD to get the textual representation. The nibble format is LSB first.


ACD39A718030C4670000

The message is roughly broken down as follows:

9Channel 1 (A – Channel 2, B – Channel 3)

A Rolling Code that changes every message
CD3 Device ID?
A71 Rolling Code? Battery?
803 Temperature in celcius, 30.8
0 Temperature positive/negative 0 is +, Non-zero is –
C4 Checksum

Here is the arduino sketch

const int INPUT_PIN = 2;
byte state = LOW;
unsigned long lastStateChange = 0;
unsigned long lastPulseWidth = 0;
const int MAX_BUFFER = 1024;
int bufferUpTo = 0;
char buffer[MAX_BUFFER];

int preambleCount = 0;

void setup() {
  Serial.begin(115200);
  pinMode(INPUT_PIN, INPUT_PULLUP);
  attachInterrupt((INPUT_PIN), changed, CHANGE);
}

void changed() { }

void receivePulse(unsigned long lowPulseWidth, unsigned long highPulseWidth) {
  
  char last = bufferUpTo != 0 ? buffer[bufferUpTo - 1] : '0';
  if (highPulseWidth >= 320 && highPulseWidth < 1350) {
    if (highPulseWidth > 615) {
      buffer[bufferUpTo++] = '0';
      buffer[bufferUpTo++] = '1';
    }
    else {
      if (bufferUpTo != 0 && lowPulseWidth >= 350 && lowPulseWidth < 850) {
        buffer[bufferUpTo++] = last;
      } else if (lowPulseWidth >= 850 && lowPulseWidth < 1400) {
        buffer[bufferUpTo++] = '0';
      } else {
        if (bufferUpTo > 10) {
          //Serial.print("low-out ");
          //Serial.println(lowPulseWidth);
          printResult(buffer, bufferUpTo);
        }
        bufferUpTo = 0;
      }
    }
  } else {
    if (bufferUpTo > 10) {
      //Serial.print("high-out ");
      //Serial.println(highPulseWidth);
      printResult(buffer, bufferUpTo);
    }
    bufferUpTo = 0;
  }
  
  if (bufferUpTo >= MAX_BUFFER - 2) {
    bufferUpTo = 0;
  }
}

void printResult(char* buf, int bufferUpTo) {
  char string[150];
  char result[50];
  char checksum[5];
  buffer[bufferUpTo++] = 0;
  //Serial.println(bufferUpTo);
  Serial.println(buf);
  
  char* remaining = buf;
  do {
    remaining = decodeBuffer(remaining, result, checksum);
    if (remaining != 0) {
      bool checksumOK = checksum[0] == result[13] && checksum[1] == result[12];
      sprintf(string, "%s - temp = %c%c%c.%c Checksum %s %s", result, result[11] != '0' ? '-' : '+', result[10], result[9], result[8], checksumOK ? "OK" : "FAILED", checksum);
      Serial.println(string);
    }
  } while (remaining != 0 && remaining - buf < bufferUpTo);
}

char* decodeBuffer(char* buf, char* strResult, char* strChecksum) {
  unsigned char result[10];
  for (int i = 0; i < sizeof(result); i++) {
    result[i] = 0;
  }

  const char* SEARCH_PATTERN = "0101010110011001";

  char* p = strstr(buf, SEARCH_PATTERN);
  if (!p) {
    return 0;
  }

  //printf("found\n");
  p += strlen(SEARCH_PATTERN) + 1;
  char* start = p;
  for (int cur = 0; *p != 0 && *(p + 1) != 0 && (cur < sizeof(result)*8); p += 2, cur++) {
    int b = cur % 8;
    if (*p == '1') {
      result[cur / 8] |= 1 << (b < 4 ? b + 4 : b - 4);
    }
  }

  for (int i = 0; i < sizeof(result); i++) {
    sprintf(strResult+i*2, "%02X", result[i]);
  }

  const int expectedMessageSize = 6;
  int checksum = 0;
  for (int i = 0; i < expectedMessageSize; i++) {
    checksum += ((result[i] & 0xF0) >> 4) + (result[i] & 0x0F);
  }
  
  sprintf(strChecksum, "%02X", (char)checksum);

  return p;
}

void loop() {
  // put your main code here, to run repeatedly:
  byte oldState = state;
  state = digitalRead(INPUT_PIN);
  if (state == oldState) {
    return;
  }

  unsigned long pulseWidth = micros() - lastStateChange;
  lastStateChange = micros();

  if (state == LOW) {
    receivePulse(lastPulseWidth, pulseWidth);
  }
  
  lastPulseWidth = pulseWidth;

  if (pulseWidth >= 600 && pulseWidth < 1350) {
    preambleCount++;
  } else {
    preambleCount = 0;
  }
  
  if (preambleCount == 32) {
    Serial.println(micros());
    preambleCount = 0;
  }
}

 

Example output:

ACD39A718030C4670000 - temp = +30.8 Checksum OK 4C

]]>
https://loune.net/2018/01/decoding-the-oregon-scientific-temperature-sensor/feed/ 6
Running shell (bash) commands in .NET Core C# https://loune.net/2017/06/running-shell-bash-commands-in-net-core/ https://loune.net/2017/06/running-shell-bash-commands-in-net-core/#comments Tue, 13 Jun 2017 12:49:40 +0000 https://loune.net/?p=546 In a lot of languages and platforms, you can easily execute shell or bash commands – like using back tick for example in PHP:
[php]
`echo hello`;
[/php]

In the .NET Core world, it’s a little bit more involved – so I wrote a helper class:

[csharp]
using System;
using System.Diagnostics;

public static class ShellHelper
{
public static string Bash(this string cmd)
{
var escapedArgs = cmd.Replace("\"", "\\\"");

var process = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = "/bin/bash",
Arguments = $"-c \"{escapedArgs}\"",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};

process.Start();
string result = process.StandardOutput.ReadToEnd();
process.WaitForExit();

return result;
}
}

[/csharp]

It’s an extension method, so after importing the namespace (if different), you can use it like this:

[csharp]
var output = "ps aux".Bash();
[/csharp]

output will contain the STDOUT of the result. Currently STDERR is not captured, but the above could easily be modified to do just that by changing the property RedirectStandardOutput and reading process.StandardError.

]]>
https://loune.net/2017/06/running-shell-bash-commands-in-net-core/feed/ 15
Simple plus to minus icon transition animation in CSS https://loune.net/2017/05/simple-plus-to-minus-icon-transition-animation-in-css/ https://loune.net/2017/05/simple-plus-to-minus-icon-transition-animation-in-css/#respond Thu, 04 May 2017 00:00:21 +0000 https://loune.net/?p=537 Here’s a simple pure CSS, plus to minus icon transition. The code is a mixin in SCSS, and currently transitions on :hover, but the :hover can be changed to a class like .is-minus.

Here’s the codepen as well: https://codepen.io/anon/pen/JNywpQ

[css]
@mixin plusMinus($width, $lineWidth, $color) {
box-sizing: border-box;
transition: transform 0.3s;
width: $width;
height: $width;
transform: rotate(180deg);
position: relative;

&:hover {
transform: rotate(0deg);
}
&::before {
content: ”;
display: block;
width: $width;
height:0px;
border-bottom: solid $lineWidth $color;
position: absolute;
bottom:$width /2 – $lineWidth/2;
transform: rotate(90deg);
transition: width 0.3s;
}
&:hover::before {
content: ”;
display: block;
width: 0px;
height:0px;
border-bottom: solid $lineWidth $color;
position: absolute;
bottom:$width /2 – $lineWidth/2;
transform: rotate(90deg);
}
&::after {
content: ”;
display: block;
width: $width;
height:0px;
border-bottom: solid $lineWidth $color;
position: absolute;
bottom:$width /2 – $lineWidth/2;
}
}

.icon {
@include plusMinus(24px, 2px, #a1a1a1);
}

[/css]

]]>
https://loune.net/2017/05/simple-plus-to-minus-icon-transition-animation-in-css/feed/ 0
Using AWS S3 as a database with PouchDB https://loune.net/2017/04/using-aws-s3-as-a-database-with-pouchdb/ https://loune.net/2017/04/using-aws-s3-as-a-database-with-pouchdb/#respond Sat, 08 Apr 2017 07:14:25 +0000 https://loune.net/?p=525 While investigating various options for a managed database solution on Amazon Web Services, I came up with an idea: What if we use Amazon’s S3 file hosting solution as a database? My requirements was that it should be a document database and it should run as cheaply as possible.

There were several obvious options already available: SimpleDB, which looks like it’s deprecated and DynamoDB, which looks to be its successor. DynamoDB is KKV NoSQL database which is supposed to scale infinitely. The pricing is reasonable, however, you have to specify the read and write capacity, and pay an on-going cost based on what you want provisioned, even if you don’t use up to the capacity. This meant that you will essentially have to pay more than your actual usage, and you will have to keep monitoring the usage levels and adjust as necessary, a maintenance hassle.

There’s actually another NoSQL database on AWS, and that’s S3. S3 is basically a huge key value store, sorted by the key. Even though the main use case is for storing files, the underlying architecture itself is hardly a file system. It automatically partitions your data inside a bucket and maintains a primary index for the key. It’s design probably inspired DynamoDB. The costs of S3 is minuscule and pay-as-you-go. They charge essentially on storage, bandwidth and API calls. For small workloads with irregular demand, this would be a big cost saving compared to using DynamoDB, where dedicated capacity needs to be provisioned.

To effectively program against S3 as a database, we will need to create an API. I’ve previously used PouchDB, which is a small Javascript based NoSQL database inspired by CouchDB. PouchDB allows the creation of custom storage backends, thus allowing data to be stored in memory, in the browser IndexedDB or another space. There isn’t a storage backend for S3, so I thought why not make one?

LevelUP/LevelDOWN

There is an existing PouchDB storage backend that uses LevelUP, which is a high-level API that wraps LevelDB, a very basic NoSQL database developed by Google. You could plug in custom backends which implement the LevelDOWN API, allowing you to use the LevelUP API to write to different backends. It has a small API surface and is the basis of larger and more feature-rich databases. A number of PouchDB backends (like memory) are constructed by wrapping a custom LevelDOWN implementation with the LevelDB plugin (see pouchdb-adapter-leveldb-core).

Due to it’s small API surface, the easiest way for PouchDB to work with S3 would be create an adapter for LevelDOWN, which I did called S3LevelDOWN. The added bonus is that you could just use it with LevelUP if you don’t need the full PouchDB functionality.

Implementing S3LevelDOWN

The most fundamental functionality is the ability to search from a start key (gt). Since S3 supports specifying a start Key, this neatly maps to the required calls of LevelDB. However, due the limited API provided by S3, there are inefficiencies due to workarounds needed to create a full LevelDOWN API. The biggest would be if you needed to reverse sort, since, S3 always return in keys in sorted ascending order, the only way to reverse is to retrieve in ascending and then reverse the list.

Performance considerations

At the end of the day, S3 is not designed as a database, hence it’s not going to yield the same performance as a normal database. It should however offer consistency in access times and scale as your storage grows.

Some additional optimisation tricks that could be employed are including data into the keys. Since there’s no batch file retrieval, separate database calls are needed to get the contents of each file, which means accessing large sets of records are slow. There is calls to list buckets, 1000 keys at a time, so including data as part of the keys allows batch retrieval. Keys can be up to 1024 in length and UTF-8 encoded.

S3 also employs partitioning based on the key prefix as noted in their documentation. So they actually advise to have more diverse prefixes in your bucket. This actually harks back to the KKV style which DynamoDB uses. You would still need a partition key, maybe as your top level folder to ensure that the data is evenly spread out to different S3 instances as to not affect the overall performance of your bucket. DynamoDB rules also apply in the sense that your prefixes should be high in cardinality. This of course may make searching by ranges harder.

And as mentioned, when listing a bucket, S3 always return in keys in sorted ascending order. If you want descending order, then that’s too bad. You have to enumerate the entire list and do a in-memory reverse sort. If you only provide the start key (lt), we would need to seek from the first key of the bucket to the start key (lt), then reverse the list in memory so that the list is emitted in reverse order. This is okay for small subsets of data but may be impossible for large sets.

Concurrency issues

A major deficiency of S3 is that there is little concurrency control. While all S3 API operations are atomic, some calls used in S3LevelDOWN like batch and get requires several S3 API operations to perform. And on top of that, pouch DB would need several LevelDOWN calls as well. Hence having two PouchDB instances accessing S3 simultaneously would result in data corruption. S3 does not support locking and only very limited optimistic concurrency control (through use of file versioning).

Conclusion

While unfortunately, we can’t use S3LevelDOWN with PouchDB, it could still be used with LevelUP, provided that you are prepared to handle errors which may arise during concurrent writes. If the documents you want stored are quite independent of each other, and very rarely modified concurrently, then this should not be an issue.

]]>
https://loune.net/2017/04/using-aws-s3-as-a-database-with-pouchdb/feed/ 0
BLEduino for Arduino 1.6 https://loune.net/2016/09/bleduino-for-arduino-1-6/ https://loune.net/2016/09/bleduino-for-arduino-1-6/#respond Thu, 08 Sep 2016 11:51:46 +0000 https://loune.net/?p=513 For the past year or so, my BLEduino laid dormant in the cupboard. Yesterday, I decided to break it out for a new project. While I used Arduino 1.0.x for the BLEduino previously, I now have Arduino 1.6. Unfortunately, I discovered that BLEduino isn’t compatible with it – The hardware core files were for 1.0.x only. I tried to use 1.0.6 on my Mac OS X 10.11, but every time I tried uploading a sketch, the following error occurs:


processing.app.SerialException: Error touching serial port '/dev/tty.usbmodem1421'.
at processing.app.Serial.touchPort(Serial.java:123)
at processing.app.debug.AvrdudeUploader.uploadViaBootloader(AvrdudeUploader.java:203)
at processing.app.debug.AvrdudeUploader.uploadUsingPreferences(AvrdudeUploader.java:67)
at processing.app.Sketch.upload(Sketch.java:1666)
at processing.app.Sketch.exportApplet(Sketch.java:1622)
at processing.app.Sketch.exportApplet(Sketch.java:1594)
at processing.app.Editor$DefaultExportHandler.run(Editor.java:2382)
at java.lang.Thread.run(Thread.java:695)
Caused by: gnu.io.UnsupportedCommOperationException: Invalid Parameter
at gnu.io.RXTXPort.setSerialPortParams(RXTXPort.java:171)
at processing.app.Serial.touchPort(Serial.java:113)
... 7 more

A search on the internet seems to indicated that this was a bug in the Arduino IDE, fixed in 1.5 later versions. I decided the only way to resolve this issue is if I port the hardware core files from 1.0 to 1.6. Luckily enough, Arduino wiki provides a handy migration guide. Within half an hour, I got BLEduino working on Arduino 1.6. I’ve posted my changes on GitHub, for anybody interested: BLEduino Arduino 1.6 hardware files. Hopefully, someone finds this useful.

]]>
https://loune.net/2016/09/bleduino-for-arduino-1-6/feed/ 0
Using log4j2 (2.3) with Android https://loune.net/2016/05/using-log4j2-2-3-with-android/ https://loune.net/2016/05/using-log4j2-2-3-with-android/#comments Sat, 07 May 2016 10:23:01 +0000 https://loune.net/?p=492 The versatile log4j is a popular logging framework for Java. Log4j 2 brings new advanced features and extensibility. Unfortunately, out of the box, it’s not very Android friendly. I spent a good day trying to perfect the usage and integration. Given the difficulties and workarounds required, I would hesitate to use Log4j2 for any Android project. This blog post is part commentary, part guide. If you really want to use it, check out my log4j2-android github for an example project. Hopefully this helps somebody out there.

The latest versions of log4j require Java 7. Since Android does not have full support for Java 7 when your app compatibility is under API 19, the latest version you could use that’s Java 6 compatible is log4j 2.3. This is the version that we will use.

Add these dependencies to your app build.gradle:

[java]
dependencies {

compile ‘org.apache.logging.log4j:log4j-api:2.3’
compile ‘org.apache.logging.log4j:log4j-core:2.3’
[/java]

Reflection Everywhere!!

One the annoying things I found was that Log4j 2 used reflection heavily, especially on app start up when it tries to initialise all its plugins. The effect is that app load time is slightly longer. Reflection also means you need to put exceptions for proguard.

LogcatAppender

Log4j allows you to configure different appenders. Common appenders are the ConsoleAppender and FileAppender. ConsoleAppender uses the Java System.err and System.out to print log messages. In Android, they get routed to Logcat, but they will all be in the INFO category and have no ability to specify a tag. With log4j, you could create your own appender plugins, so I’ve defined a LogcatAppender. The appender maps logger.error to Log.e, logger.debug to Log.d, etc etc and uses the logger name as the tag.

AndroidLookup

Another type of plugin you could create is a Lookup. Lookups are custom variables which you can reference in your log config files. When specifying the file path to your log file, a lookup value that will come in handy is the android data directory. The AndroidLookup I’ve created allows you to use ${android:filesdir}, ${android:externalfilesdir} or ${android:logfilesdir} placeholder variables.

Configuration

By default log4j searches and loads its configuration from the file system using a bunch of rules. This is not ideal in an Android environment where the app is packaged an an APK. The default behaviour can be overridden by providing a custom ConfigurationSource to the LoggerContext. I’ve put the log4j XML configuration in a raw resource and implemented a custom ContextSelector to initialise the LoggerContext with the custom config. All of this is then tied together by the AndroidLog4jHelper class I’ve created.

AndroidLog4jHelper also injects plugins

There is another purpose to AndroidLog4jHelper and that is to inject plugins. As mentioned, Log4j uses reflection heavily. One of the problems is that Android/ART/Dalvik is not Java, and hence some assumptions that are made in Log4j, based on the JRE, aren’t applicable to Android. Typically, the PluginManager.addPackage method is used to register plugins. It works by finding the package folder in the .jar and enumerating the .class files. Then it would use ClassLoader and reflection to find the @Plugin annotations to register. In Android, we don’t have .class files in a .jar (or apk), hence it doesn’t find anything. To make the LogcatAppender and AndroidLookup plugins work correctly, I’ve devised a hack – Using reflection, I manually injected the plugins to a privately held Map in the PluginRegistry. It would be helpful if Log4j natively provide a method to manually register plugins by passing the class type.

Using AndroidLog4jHelper and Plugins

The key classes for this log4j android solution are in this package folder. Copy them to your project.

To use the AndroidLog4jHelper, in your Application sub class onCreate method, put:

[java]
if (BuildConfig.DEBUG) {
AndroidLog4jHelper.initialise(this.getApplicationContext(), R.raw.log4j_debug);
} else {
AndroidLog4jHelper.initialise(this.getApplicationContext(), R.raw.log4j_release);
}
[/java]

Note that we are specifying different XML configs for debug and release. If you only require one config, then you don’t need to have the if condition. Create the raw resources log4j_debug.xml and log4j_release.xml. An example XML config which uses LogcatAppender and AndroidLookup:

[xml]
<?xml version="1.0" encoding="UTF-8"?>

<Configuration status="debug">
<Appenders>
<Logcat name="Logcat">
<ThresholdFilter level="ALL" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%m" />
</Logcat>
<RollingFile name="RollingFile" fileName="${android:logfilesdir}/app.log" filePattern="app-%i.log.gz">
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="1 MB"/>
</Policies>
<DefaultRolloverStrategy max="20"/>
</RollingFile>
</Appenders>

<Loggers>
<Root level="DEBUG">
<AppenderRef ref="Logcat"/>
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
[/xml]

In the class in which you want to log, put:

[java]
private static final Logger logger = LogManager.getLogger("MyClass");
[/java]

Then you can use:

[java]
logger.info("Log4j2 succcess");
[/java]

Using the config above, you should see the log messages appear in Logcat. Messages will also be logged to the filesystem, under [your ext data directory]/logs/app.log

Proguard rules for Log4j

When releasing the APK to the public, a best practise is to utilise proguard to reduce the size of the file and obfuscate methods from sticky beaks. Since Log4j uses reflection, here are the proguard rules required for it to run properly. The presence of -keepattributes Signature may compromise code obfuscation, but unfortunately is required for log4j to work properly.

[java]
-dontwarn org.apache.logging.log4j.**
-keepattributes Signature
-keep class org.apache.logging.log4j.** { *; }
-keep class net.loune.log4j2android.** { *; }
[/java]

Exclude miscellaneous META-INF files

If you want to avoid build errors when generating an APK (You do!!!), you need to exclude some dupe’d META-INF files that are present in the log4j2 jar files. Modify your app build.gradle as such:

[java]
android {

packagingOptions {
exclude ‘META-INF/LICENSE’
exclude ‘META-INF/NOTICE’
exclude ‘META-INF/DEPENDENCIES’
}
[/java]

In conclusion, Log4j2 could be comfortably used with Android, but with some compromises. If the start up performance and proguard rules are acceptable to you, and you like the extensibility of the various L4J plugins, then Log4j2 might be the logging solution for you.

]]>
https://loune.net/2016/05/using-log4j2-2-3-with-android/feed/ 14
Building an Android phone connected Door Bell with Light Blue Bean’s iBeacon https://loune.net/2016/04/building-an-android-phone-connected-door-bell-with-light-blue-beans-ibeacon/ https://loune.net/2016/04/building-an-android-phone-connected-door-bell-with-light-blue-beans-ibeacon/#comments Sat, 30 Apr 2016 00:47:26 +0000 http://siphon9.net/loune/?p=438 The Light Blue Bean built by Punch Through Design is a versatile Arduino device with Bluetooth Low Energy (BLE) built in. The Bean’s default 3v battery could typically last a month when running a minimal sketch. A door bell button is possibly the simplest arduino device you could possibly build. A press of the button would notify an android device through BLE that someone is at the door. This post will provide an idea on how this could be built using minimal power (on the Bean) and minimal code.

Why use iBeacon?

The two typical ways for a Bean to talk with another device such as an iPhone or Android phone is either to use a virtual serial connection or scratch characteristics. Both ways have their advantages and disadvantages against each other. Virtual serial tends to be for real time communication whereas the scratch characteristics are more for lower frequency, fire and forget updates. Both methods require an active connection between the Bean and the other device, and you could only have one connection at a time. What if you want several devices to receive the door bell notification?

There is a third way – Using iBeacon. iBeacon is an Apple developed protocol that piggy backs off BLE. It broadcasts messages to all nearby BLE-capable devices. The common use-case is to broadcast advertisements and special offers to shoppers that have arrived at a retail shop housing an iBeacon. The Light Blue Bean allows iBeacon mode to be activated.

iBeacon piggy backs of BLE advertisements which the Bean is constantly sending every 500ms, to tell nearby devices that it is alive. Hence embedding messages within these broadcast advertisements carry very little extra cost to power. These advertisements are also passively received by all nearby devices, hence allowing multiple devices to receive and respond to messages. No connection is required. However, the downsides compared to the two aforementioned ways of communication are that:

  • Communication is only one-way – Bean to phone
  • There is no pairing connection, hence no encryption
  • The Bean only allows 6 bytes of user-adjustable data transmission (2-bytes of the UUID, 2-bytes Major, 2-bytes Minor)

These limitations however are fine for the an IoT door bell. We only need a boolean in our message – button is pressed or button is not pressed.

It may also be wise to consider security implications – There are two security issues:

  • An attacker can spoof the BLE advertisements, sending prank door bell rings – a minor annoyance
  • An attacker can monitor door bell rings – which if they are in range, they could just as well see that there are people at the front door

Both of these issues could be mitigated by adding encryption or some HOTP based system, but that’s out of the scope of this project.

Building the Door Bell Button

The button is basically a Bean that monitors a click, which is when a circuit is closed. It is based off the simple Arduino code which wires up a PIN D0 to a switch and then the ground. Setting D0 to INPUT_PULLUP allows us to avoid using an external pull-up (or pull-down) resistor, but means that when the pin D0 is HIGH, it is an open circuit, the button is not pressed. When the pin D0 is LOW, the button is pressed.

We have manually enabled iBeacon using the Bean Loader, entering the default parameters for the iBeacon device. These parameters are changeable in Arduino using setBeaconParameters. This will allow us to indicate whether the button is pressed or not. It is important that you have in setup() Bean.enableConfigSave(false); as by default, the Bean writes to non-volatile memory every time BLE settings are changed. This memory is only rated up to 20,000 write cycles. In this example, we will set minor_id to 1 if the button is pressed, 0 if the button is not pressed. We toggle the flag for a period of three seconds to ensure our signal is read by the Android device.

[code]
if (digitalRead(0) == LOW) {
Bean.setBeaconParameters(BEACON_UUID, 0, 1);
delay(3000);
Bean.setBeaconParameters(BEACON_UUID, 0, 0);
}
[/code]

You may notice that delay() is used instead of Bean.sleep(). The reason is that we want execution to be paused for a full 3 seconds. Bean.sleep() could be interrupted by events, such as the one which we are setting up next.

To maximise power savings, we want the Arduino controller to be sleeping until there are events to respond to, such as a button press. Hence we use attachPinChangeInterrupt in setup() that wakes the Arduino controller when D0 changes from HIGH to LOW or vice-versa. triggerDoorbell method is empty as we want to keep our logic in loop()

[code]
attachPinChangeInterrupt(0, triggerDoorbell, CHANGE);
[/code]

In our loop we will add sleep(MAX_SLEEP), MAX_SLEEP being a constant 0xFFFFFFFF. As mentioned, Bean.sleep() will be interrupted by pin changes.

[code]
Bean.sleep(MAX_SLEEP);
[/code]

During testing, I found a delay of 3 to 4 seconds in the broadcasting of the new BLE advertisement after pressing the button. After a bit of trial and error, toggling enableAdvertising seemed to fire a new BLE advertisement with the new beacon values immediately.

[code]
if (digitalRead(0) == LOW) {
Bean.enableAdvertising(false);
Bean.setBeaconParameters(BEACON_UUID, 0, 1);
Bean.enableAdvertising(true);
delay(3000);
Bean.enableAdvertising(false);
Bean.setBeaconParameters(BEACON_UUID, 0, 0);
Bean.enableAdvertising(true);
}
[/code]

Here is the final Arduino sketch. setLed was added for debugging purposes, as well as some simple debouncing logic.

[code]
#include <PinChangeInt.h>
int MAX_SLEEP = 0xFFFFFFFF;
uint16_t BEACON_UUID = 0x1234;

void setup() {
Bean.enableConfigSave(false);
pinMode(0, INPUT_PULLUP);
attachPinChangeInterrupt(0, triggerDoorbell, CHANGE);
Bean.enableAdvertising(false);
Bean.setBeaconParameters(BEACON_UUID, 0, 0);
Bean.enableAdvertising(true);
}

void loop() {
if (digitalRead(0) == LOW) {
// debounce
Bean.sleep(200);
if (digitalRead(0) == LOW) {
Bean.enableAdvertising(false);
Bean.setBeaconParameters(BEACON_UUID, 0, 1);
Bean.enableAdvertising(true);
Bean.setLed(255,255,255);
delay(3000);
Bean.enableAdvertising(false);
Bean.setBeaconParameters(BEACON_UUID, 0, 0);
Bean.enableAdvertising(true);
Bean.setLed(0,0,0);
}
}

Bean.sleep(MAX_SLEEP);
}

void triggerDoorbell() {
// sleep interrupted, loop() should run
}

[/code]

Writing an Android iBeacon Detector

On the Android side, we need to build an iBeacon detector, which is basically a BLE scanner. BLE support began in Android 4.3, but the APIs were improved in Android 5.0 lollipop. Using BluetoothLeScanner we can scan for BLE advertisements, which will contain the UUID, major and minor IDs that we set earlier. From that point, we just need to check if minor is 0 or 1, then we can show a door bell notification.

Using BluetoothLeScanner, we created a wrapper class BeaconScanner that emits BeaconInfo every time a beacon is detected. To minimise the delay between the button press and the bell ringing, we set the SCAN_MODE_LOW_LATENCY flag. This reduces the delay to less than a second. Without it, the delays ranges from less than a second to a few seconds. The downside is that it uses more power.

BeaconScanner.java

[java]
package net.loune;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.util.SparseArray;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.UUID;

/**
* Created by loune on 26/12/2015.
*/
public class BeaconScanner {
private BluetoothAdapter bluetoothAdapter;
private BluetoothLeScanner bluetoothLeScanner;
private OnBeaconDetectedListerner listener;

public void setListener(OnBeaconDetectedListerner listener) {
this.listener = listener;
}

protected ScanCallback scanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
BluetoothDevice device = result.getDevice();
ScanRecord scanRecord = result.getScanRecord();
SparseArray<byte[]> manufacturerData = scanRecord.getManufacturerSpecificData();
if (manufacturerData.size() == 0) {
return;
}

int manufacturerId = manufacturerData.keyAt(0);
byte[] data = manufacturerData.get(manufacturerId);

if (data.length < 23) {
return;
}

int rssi = result.getRssi();
double dist = calculateAccuracy(data[22], (double) rssi);
byte[] uuid = Arrays.copyOfRange(data, 2, 18);
BeaconInfo info = new BeaconInfo(
device.getName(),
device.getAddress(),
(short)manufacturerId,
(short)(((data[0] & 0xFF) << 8) | (data[1] & 0xFF)),
getUUIDFromByteArray(uuid),
(short)(((data[18] & 0xFF) << 8) | (data[19] & 0xFF)),
(short)(((data[20] & 0xFF) << 8) | (data[21] & 0xFF)),
data[22],
rssi,
dist);

if (listener != null)
listener.onBeaconDetected(device, info);
}
};

public BeaconScanner() {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}

public void startScan() {
bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();

if (bluetoothLeScanner == null) {
// bluetooth not enabled?
return;
}

ScanSettings settings = new ScanSettings.Builder()
.setReportDelay(0)
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();

bluetoothLeScanner.startScan(null, settings, scanCallback);
}

public void endScan() {
bluetoothLeScanner.stopScan(scanCallback);
bluetoothLeScanner = null;
}

// http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing
// returns approximate iOS distance in metres
protected static double calculateAccuracy(int txPower, double rssi) {
if (rssi == 0) {
return -1.0; // if we cannot determine accuracy, return -1.
}

double ratio = rssi*1.0/txPower;
if (ratio < 1.0) {
return Math.pow(ratio,10);
}
else {
double accuracy = (0.89976)*Math.pow(ratio,7.7095) + 0.111;
return accuracy;
}
}

private static UUID getUUIDFromByteArray(byte[] bytes) {
ByteBuffer bb = ByteBuffer.wrap(bytes);
long high = bb.getLong();
long low = bb.getLong();
UUID uuid = new UUID(high, low);
return uuid;
}

public interface OnBeaconDetectedListerner {
void onBeaconDetected(BluetoothDevice device, BeaconInfo beaconInfo);
}
}

[/java]

BeaconInfo.java

[java]
package net.loune;

import java.util.UUID;

/**
* Created by loune on 26/12/2015.
*/
public class BeaconInfo {
private String name;
private String address;
private short manufacturerId;
private short beaconCode;
private UUID beaconUUID;
private short major;
private short minor;
private int referenceRssi;
private int rssi;
private double distance;

public String getName() {
return name;
}

public String getAddress() {
return address;
}

public short getManufacturerId() {
return manufacturerId;
}

public short getBeaconCode() {
return beaconCode;
}

public UUID getBeaconUUID() {
return beaconUUID;
}

public short getMajor() {
return major;
}

public short getMinor() {
return minor;
}

public int getReferenceRssi() {
return referenceRssi;
}

public int getRssi() {
return rssi;
}

public double getDistance() {
return distance;
}

public BeaconInfo(String name, String address, short manufacturerId, short beaconCode, UUID beaconUUID, short major, short minor, int referenceRssi, int rssi, double distance) {
this.name = name;
this.address = address;
this.manufacturerId = manufacturerId;
this.beaconCode = beaconCode;
this.beaconUUID = beaconUUID;
this.major = major;
this.minor = minor;
this.referenceRssi = referenceRssi;
this.rssi = rssi;
this.distance = distance;
}
}

[/java]

Using BeaconScanner

BeaconScanner exposes an event handler, allowing you to set a OnBeaconDetectedListerner. In our listener, we sound a notification when we detect a beacon with Minor = 1.

[java]
BeaconScanner scanner = new BeaconScanner();
scanner.setListener(new BeaconScanner.OnBeaconDetectedListerner() {
long ignoreUntil = 0;
@Override
public void onBeaconDetected(BluetoothDevice device, BeaconInfo beaconInfo) {
if (beaconInfo.getMajor() == 0 && beaconInfo.getMinor() == 1) {
if (ignoreUntil > System.currentTimeMillis())
return;

// play sound and show snack bar notification
try {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
} catch (Exception e) {
e.printStackTrace();
}
Snackbar.make(fab, "GET THE DOOR", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();

// ignore any beacons for the next 3.5 seconds (as we send bursts in the bean)
ignoreUntil = System.currentTimeMillis() + 3500;
}
}
});
scanner.startScan();
[/java]

A button for anything really.

Although, this example is for a simple door bell, it can really be used as a simple remote trigger for anything, like a wireless presenter, as long as you are aware of the issues surrounding security.

]]>
https://loune.net/2016/04/building-an-android-phone-connected-door-bell-with-light-blue-beans-ibeacon/feed/ 5
Issue with Xaml Designer – An error occurred loading this property page https://loune.net/2016/04/issue-with-xaml-designer-an-error-occurred-loading-this-property-page/ https://loune.net/2016/04/issue-with-xaml-designer-an-error-occurred-loading-this-property-page/#comments Sun, 03 Apr 2016 10:04:32 +0000 https://loune.net/?p=502 Xaml Designer > […]]]> So after installing Visual Studio 2015 Update 2, my Xaml Designer decided to stop working. Every time I open the designer by clicking on a xaml file, it would show an error dialog that says “Visual Studio has encountered an unexpected error.” – not very helpful. Going to the menu, Options > Xaml Designer > General property page would yield an error “An error occurred loading this property page”.

I then tried re-installing Visual Studio 2015. Same issue. I then tried opening Expression Blend, it doesn’t work, but I got a some more interesting clues – it tells me to check ActivityLog.xml – In it, there was a telling error:

SetSite failed for package [XamlDesignerPackage][This access control list is not in canonical form and therefore cannot be modified.

Basically my permissions were corrupted somewhere in some file. I had a hunch. A test by logging on to a fresh Windows user account and opening VS xaml editor confirmed that the issue was limited to my profile account. I tried remove all traces of Visual Studio from profile but removing the obvious AppData folder didn’t fix the issue. There were just too many places it hides files. As a last resort, I reset all permissions on my profile folder such that I was the owner and had write access and surprise! it works!! Now I know what to try next time.

]]>
https://loune.net/2016/04/issue-with-xaml-designer-an-error-occurred-loading-this-property-page/feed/ 1