Air Quality Sensor (PMS5003)

The postUpdate and sendCommand actions don’t like numbers, particularly primitive numbers. Try:

Outside_PM1.postUpdate(pm1)

If that doesn’t work try:

val Number pm1 = new Number(bb.getShort)
postUpdate(Outside_PM1, pm1.toString)

First gives:
2016-04-05 17:38:01.182 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Testing': The name '<XFeatureCallImplCustom>.potUpdate(<XFeatureCallImplCustom>)' cannot be resolved to an item or type.

Second:
2016-04-05 17:38:02.545 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Testing': Could not invoke constructor: java.lang.Number.Number()

Again duh!

val Number pm1 = new Short(bb.getShort)

Number is abstract. You can’t create one using new.

I must be tired today.

2016-04-05 17:57:24.500 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule ‘Testing’: Cannot create a duplicate value ‘pm1’.

Sorry, that was my bad

Good. I was scratching my head what that could have been.

Does this mean it works?

All good:

import javax.xml.bind.DatatypeConverter
import java.nio.*
import java.lang.*
import org.openhab.core.library.types.*

rule "Outside_Air_Quality"
when
	Item Outside_Air_Quality received update
then
	val to64 = DatatypeConverter::parseBase64Binary(Outside_Air_Quality.state.toString)
	val ByteBuffer bb = ByteBuffer::wrap(to64)
	val short start = bb.getShort
	val short length = bb.getShort
	if (start==16973 && length==28) {
		val short pm1 = bb.getShort
		postUpdate(Outside_PM1, pm1.toString)	
		val short pm25 = bb.getShort
		postUpdate(Outside_PM25, pm25.toString)	
		val short pm10 = bb.getShort
		postUpdate(Outside_PM10, pm10.toString)	
	}	
end
2 Likes

Hi Nathan,

If you have a moment can you provide an update on this part of your project?

  • How are the PMS5003 sensors working out, physically speaking? Are they durable and continuing to give accurate measurements?

  • How has the OpenHAB side of the setup been working? Have you further modified the code above in any way? Does this work with OpenHAB 2.x?

Appreciate any & all remarks, suggestions, comments on PMS5003 integration. I am looking to add 3 or 4 of these sensors to my home’s OpenHAB setup, as part of an air-filtration/HVAC control subsystem.

Thanks in advance.

I have 5 of them and they all are still working well including 1 outside in a covered but open box. I have not had to change anything in OpenHAB and I am running latest 2.x.

Thanks for the follow-up.

Can you describe the physical setup a bit? You’re using RS232 / 9600 baud output direct from the sensors, how does that get into openHAB?

What kind of wire / cable? Perhaps UTP?
What’s the longest cable run?
What kind of multi-port RS232 interface are you using on the openHAB server?

Hi,

Can anyone tell me what this syntax is about:

.forEach[b | bts.append(Integer.toHexString(b)]

which is in one of the posts above.

As far as I can tell, forEach() can take a lambda as an argument. Is

[b | bts.append(Integer.toHexString(b)]

some type of lambda syntax? Can you point me to a link where that syntax is explained?

To me the | looks like java’s bitwise OR operator, which doesn’t make any sense to me in that code. Should that code really read:

.forEach(b -> bts.append(Integer.toHexString(b) )

Thanks.

The | is a separator between the arguments passed to the lambda and they body of the lambda.

Keep in mind that the Rules DSL is not Java but a domain specific language bearing many similarities with Xtend. For all syntax questions like this, the Rules page is a good place to start. Don’t neglect the links to the Xtend docs on that page though. The syntax deviates from “normal” standards in a number of ways.

Hey, thanks for the reply.

Ah. Okay. I was searching around Java for the syntax.

Yes, RS232 9600/8/N/1 into a RS232 TTL to USB converters from ebay. Wire is 2 pair 28 gauge, longest run is about 150 feet. The RS232 TTL to USB converters all plug into a 7 port USB hub.

I like to have my ports show up in the same order and with unique names so I have the following /etc/udev/rules.d/99-usb-serial.rules file:

SUBSYSTEM=="tty", KERNELS=="2-1.3.1.1", SYMLINK+="ttyPort0", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", KERNELS=="2-1.3.1.2", SYMLINK+="ttyPort1", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", KERNELS=="2-1.3.1.3", SYMLINK+="ttyPort2", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", KERNELS=="2-1.3.1.4", SYMLINK+="ttyPort3", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", KERNELS=="2-1.3.2", SYMLINK+="ttyPort4", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", KERNELS=="2-1.3.3", SYMLINK+="ttyPort5", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", KERNELS=="2-1.3.4", SYMLINK+="ttyPort6", GROUP="dialout", MODE="0666"
SUBSYSTEM=="tty", KERNELS=="2-1.4.4", SYMLINK+="zwave", GROUP="dialout", MODE:="0666"

If you use custom names you need /etc/default/openhab2 file:

EXTRA_JAVA_OPTS="-Dgnu.io.rxtx.SerialPorts=/dev/zwave:\
/dev/ttyPort0:/dev/ttyPort1:/dev/ttyPort2:/dev/ttyPort3:/dev/ttyPort4:/dev/ttyPort5:/dev/ttyPort6 \
-Dfile.encoding=ISO-8859-1 -Duser.timezone=America/New_York"