arduino rtc setter via serial terminal (vt100)

using putty on the terminal.


#include "RTClib.h"
DateTime now;
RTC_PCF8523 rtc;

void loop() {

  if (digitalRead(15) & millis() < 5000) { //enter setup mode if d15 pulled high within 5 sec of power on.
  Serial.print("\033[?25l"); // hide cursor
  Serial.print("\033[2J"); // clear screen & home

  while (digitalRead(15)) { // stay in setup mode while d15 kept high.
    now = rtc.now();
    Serial.print("\033[0;0H"); // cursor to line 0 col 0
    uint16_t year = now.year();
    Serial.print(year, DEC);
    Serial.print('/');
    uint8_t month = now.month();
    if (month < 10) {
      Serial.print("0");
    }
    Serial.print(month, DEC);
    Serial.print('/');
    uint8_t day = now.day();
    if (day < 10) {
      Serial.print("0");
    }
    Serial.print(day, DEC);
    Serial.print(' ');
    uint8_t hour = now.hour();
    if (hour < 10) {
      Serial.print("0");
    }
    Serial.print(hour, DEC);
    Serial.print(':');
    uint8_t minute = now.minute();
    if (minute < 10) {
      Serial.print("0");
    }
    Serial.print(minute, DEC);
    Serial.print(':');
    uint8_t second = now.second();
    if (second < 10) {
      Serial.print("0");
    }
    Serial.print(second, DEC);
    Serial.print("\n\rUse keys y, m, d, h, M, s to change\n");

    if (Serial.available()) {
        switch (Serial.read()) {
            case 'Y':
            case 'y': {
                ++year;
                if (year > 2099) {year = 2000;} 
                rtc.adjust(DateTime(year, now.month(), now.day(), now.hour(), now.minute(), now.second()));
                break;
            }
            case 'm': {
                if (month > 11) {month = 0;}
                ++month;
                rtc.adjust(DateTime(now.year(), month, now.day(), now.hour(), now.minute(), now.second()));
                break;
            }
            case 'D':
            case 'd': {
                if (day > 30) {day = 0;}
                ++day;
                rtc.adjust(DateTime(now.year(), now.month(), day, now.hour(), now.minute(), now.second()));
                break;
            }
            case 'H':
            case 'h': {
                ++hour;
                if (hour > 23) {hour = 0;}
                rtc.adjust(DateTime(now.year(), now.month(), now.day(), hour, now.minute(), now.second()));
                break;
            }
            case 'M': {
                ++minute;
                if (minute > 59) {minute = 0;}
                rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), minute, now.second()));
                break;
            }
            case 'S':
            case 's': {
                ++second;
                if (second > 59) {second = 0;}
                rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), second));
                break;
            }
        }
    }
   }
  }
}

network folder listing very slow with Windows Explorer especially over VPN

I had a directory with ~2,500 subdirectories in it.
Viewing the folder with Windows Explorer on the LAN was a bit slow.
Viewing the folder over VPN was very very slow.

I thought this was an SMB version issue with the Server 2008 (not R2) machine, i.e. it not being very VPN friendly (VPN was my issue.. nobody notices it’s a bit slow on the LAN), and I was attempting to in-place upgrade it to 2012 as an interim to 2012 R2 (another story..)

I had tested a similar directory tree on a Server 2016 machine and it was rapido. I simply used xcopy to copy the directory structure without the contents, and used this to test.

So I was all set to upgrade the OS, get a shiny new SMB3, and …

Well the upgrade isn’t happening (component based servicing mess. This machine has had hundreds of updates on it since 2009.. nearly 9 years of updates have to be jigged about just so that Terminal Services Gateway role can be removed to allow the upgrade to Server 2012, and it’s just not happening.)

Anyway! I found out what was wrong. This is a little obscure.
About 900 folders in there had the +s attribute set! (System).

The quick clue was that ‘dir’ from a command prompt only listed about half the folders that were known to be in there.

I believe this was something I was asked to do ages ago, so that the company could make use of the ‘Comment’ field in windows explorer for folders. So I made a setComment script that tied into the explorer context menu, and read a message from you, then stored it in a Desktop.ini within the folder, and set the folder +S. It never got used because Explorer was flaky about displaying the comments.
The +S attribute makes Windows Explorer look into each folder for a Desktop.ini and process it.

So, my fix was as simple as:

for /d %a in (*) do attrib -s “%a”

(in the folder with all the subfolders).

Now it’s SUPER RAPIDO!

Arduino Zeitronix reader / logger

Not quite logging to SD in this code.. that part is in there but is not in use. Still working on KWP2000 & Zeitronix. Zeitronix bit is done and working well.

Here’s the Arduino / C++ code for capturing the Zeitronix stuff. I’m not bothering with the 3 byte start sequence in the output

#include 
#include 
#include 
#include 
#include 
#include 

const int chipSelect = 10;
int gotPacket = 0;
char packet[11];

void setup() {
    // Open serial communications and wait for port to open:
  Serial.begin(115200);
  Serial1.begin(9600);
  Serial1.setTimeout(100);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.print("Initializing SD card...");
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");

}


void getZeitronixPacket(char* packetpointer){
gotPacket = 0;
char buffer[32] = {0xF}; // buffer 32 bytes to make sure we find the 3 byte start sequence.
  for (int i=0; i<32; i++){
    Serial1.readBytes(&buffer[i],1);
    if (i > 1 && buffer[i] == 2 && buffer[i-1] == 1 && buffer[i-2] == 0) {
          gotPacket = 1;
          Serial1.readBytes(packetpointer,11);
          return;
    }
  }
}


void exampleStuff() {
  // make a string for assembling the data to log:
  String dataString = String(millis()) += ",";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ",";
    }
}

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
}

void loop() {
char dataString[80];

while (Serial1.available() > 32){ // wait til there's a nice chunk in the serial buffer
    getZeitronixPacket(packet);
    // this would be our logtosd() below:
    if (gotPacket == 1) {
      sprintf(dataString, "%lu,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", millis(),packet[0],packet[1],packet[2],packet[3],packet[4],packet[5],packet[6],packet[7],packet[8],packet[9],packet[10]);
      Serial.println(dataString);
    }
}

// Serial.print(".");


}

KWP2000 fmt byte deciphering

It’s all in the docs, but it sure does help to write it out..
This is the first byte, the Fmt byte. Use it to know how much data there is to capture.

0 = optional length byte present, no address bytes
1 to 3f = subtract 0 to get the length, no address bytes

40 = optional length byte present, ?? address bytes unsure [exception mode (CARB)]
41 to 7f – subtract 40 to get length, ?? address bytes unsure [exception mode (CARB)]

80 = optional length byte present, address bytes present [physical addressing]
81 to bf – subtract 80 to get length, address bytes present [physical addressing]

c0 = optional length byte present, address bytes present [functional addressing]
c1 to FF = subtract c0 to get length, address bytes present [functional addressing]

Length = service id bytes (included) to checksum (not included)
Checksum = All bytes except the checksum itself, sum, mod 256.

Datalogger for zeitronix zt-2 wideband afr plus obd2. Arduino adafruit feather m0 circuitpython

Code for https://youtu.be/b3TxFYFKEt0
This is CircuitPython. I have since re-written it in Arduino Wire (C++), and am now working on the KLine KWP2000 element of the project.

import board
import busio
import time
import adafruit_sdcard
#import adafruit_pcf8523
import microcontroller
import digitalio
import storage
import os

switch = digitalio.DigitalInOut(board.A5)
switch.direction = digitalio.Direction.INPUT
switch.pull = digitalio.Pull.UP

#Zeitronix Packet format, bytes[]
#[0] always 0
#[1] always 1
#[2] always 2
#[3] AFR
#[4] EGT Low
#[5] EGT High
#[6] RPM Low
#[7] RPM High
#[8] MAP Low
#[9] MAP High
#[10] TPS
#[11] USER1
#[12] Config Register1
#[13] Config Register2

#led = digitalio.DigitalInOut(board.D13)
#led.direction = digitalio.Direction.OUTPUT

SD_CS = board.D10
# Connect to the sdcard and mount the filesystem.
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
cs = digitalio.DigitalInOut(SD_CS)
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")

uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)

#date = rtc.datetime() # will use this for the filename
# this board doesn't seem to have enough ram for the rtc library & sd & everything else going on here.. getting an allocation error
#filename = str(date.tm_year) + "-" + str(date.tm_mon) + "-" + str(date.tm_mday) + "-" + str(date.tm_hour) + "" + str(date.tm_min)
filename = "2017-09-11-test"
filename += ".csv"

def getPacket():
	rcdbyte = [None] * 3
	packet = [0] * 15
	packet[0] = time.monotonic()
	i = 0
	while True:
		rcdbyte[i] = uart.read(1)	#read a single byte
		if rcdbyte[i] == None:	#if we got an empty byte, assume the serial link is down, and return zeros.
			return packet
		if rcdbyte[i] == b'\x02' and rcdbyte[i-1] == b'\x01' and rcdbyte[i-2] == b'\x00': # we got our 3 bytes in order for the start of packet
			packet[1] = 0
			packet[2] = 1
			packet[3] = 2

			for x in range(4, 15):	#get the rest of the packet.
				byte = uart.read(1)
				if byte == None:	#if we got an empty byte, assume the serial link is down, and return zeros.
					packet[x] = 0
					return packet
				packet[x] = byte[0]
			return packet
		i += 1
		if i == 3:
			i = 0

#this is currently configured so that you have to short the pin to ground momentarily to start logging, then again to stop.
while True:
	if switch.value == False:
		time.sleep(0.2)
		f = open("/sd/" + filename, "w")
		while switch.value == True:
			packet = getPacket()
			f.write('{}\n'.format(packet))
			print('.',end='')
		f.close()
		time.sleep(0.2)

Remote Desktop printer driver name mismatch

Years ago.. about a decade ago, we used to use some kind of .ini or .inf file to tally up mismatched printer driver names between client & server when using Terminal Services printer redirection.
It’s long winded process, and I can’t really find any information on how to do it now. I did eventually find the information about a month ago, but it wasn’t easy to find, and when I looked at it I decided I just wanted to go home.

This problem is beginning to occur more frequently again now between Windows 10 and Windows 7. The situation is a Windows 7 Professional computer in the office, and a Windows 10 computer at home, trying to use Remote Desktop to access the Windows 7 computer.

Both HP and Dell, have different names in their Windows 7 drivers vs. the Windows 10 drivers.

So when faced with the same problem again today, I tried a different fix, and it seemed to work just fine.

I changed the driver name in the registry, restarted the Print Spooler, and the name changed in the drivers list. I disconnected / reconnected to Remote Desktop, and the printer redirection worked as it should.

As you can see in the pictures below, the key itself just needs renaming under HKLM\SYSTEM\CurrentControlSet\Control\Print\Environments\Windows x64\Drivers\Version-3 (or whatever for your specific driver).

In the screenshot below, I am adding “GDI” to the end of the “Dell B1165nfw Mono MFP” driver name, so that it matches with the new Windows 10 laptop that the person is connecting from.

Here’s the driver name on the Windows 7 Pro RDP host computer at the company:

Here’s the driver name on the Windows 10 client RDP client:

and here is me altering that name back on the Windows 7 Pro computer. I have added ” GDI” to the end, so that the names match.
The print spooler service needed restarting for the updated name to appear.

Prevent server from rebooting *before* remote logon

You’re at the logon screen. The server says “Automatic restart will occur today”. If you log on, it will either restart now, or when you’re finished, and you’ll get some support calls when it’s down!

From your favourite remote support tool, run the following command *before* logging on:

reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v NoAutoRebootWithLoggedOnUsers /t REG_DWORD /d 1 /f

If you leave the password prompt (click back to the Ctrl-Alt-Del screen), and then go back to log on, you should see that the “Automatic restart will occur today” part of the warning is gone, and you can safely log on.

nginx error 500 php

in /etc/php-fpm.d/www.conf:

catch_workers_output = yes

and most importantly.. comment out the 5xx html page in nginx.conf, so you can see actual errors. Which in my case turned out to be permissions of /var/lib/php/[session, peclxml, opcache, wsdlcache]. They were still group owned by ‘apache’ instead of nginx

/etc/nginx/nginx.conf:

#display some actual useful errors please....
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }

Centos / Fedora firewalld firewall-cmd

I can never remember this…

firewall-cmd --list-all-zones

Look to see which is ‘active’. Should be FedoraServer on Fedora Server. Then..

firewall-cmd --zone=FedoraServer --add-port=80/tcp --permanent

Annoyingly, the –permanent means ‘just add to the startup configuration, but don’t do anything now’. If you leave off the –permanent, then it takes effect right away but only affects the running configuration and will be lost after a restart.

Either way, you need two commands – either the –permanent command above, followed by

firewall-cmd --reload

or, and this is probably wiser in case you do something wrong and lock yourself out, you should do the command without –permanent, then check that all works (no –reload will be needed), then add it in again with –permanent so that the rule will be present after a future restart.

So, in summary:

firewall-cmd --zone=FedoraServer --add-port=80/tcp

(check that things are as you want them)

firewall-cmd --zone=FedoraServer --add-port=80/tcp --permanent

for localhost only stuff (e.g. powerdns stats on 127.0.0.1:8081)

firewall-cmd --zone=trusted --add-port=8081/tcp
firewall-cmd --zone=trusted --add-port=8081/tcp --permanent

To remove / undo:

firewall-cmd --zone=FedoraServer --remove-port=80/tcp
firewall-cmd --zone=FedoraServer --remove-port=80/tcp --permanent

For some known services (not sure which.. maybe it just uses /etc/services ?) you can give the service name instead of the port/protocol:

--add-service=http

instead of

--add-port=tcp/80

etc.

Petya / NotPetya cyber attack 27th June 2017

Petya (a.k.a NotPetya) is another ransom-ware file-encrypting virus worm. The latest big thing.

Apparently it spreads through the same mechanism as the WannaCry virus (NHS cyber attack May 2017), but there are also reports of it being sent through emails.
That method of spreading from one computer to another was due to a security flaw in Microsoft Windows. The code to exploit this flaw, which the US government found years ago but kept to themselves, had been called EternalBlue. A patch/fix for this was released by Microsoft in March 2017, and also included in subsequent update roll-ups.

During the NHS cyber attack crisis, I took steps to ensure that all client’s computer had this and other important updates installed. For this reason, you are already patched against EternalBlue, however you must still be vigilant with regard to opening email attachments.

As it happens, security researchers have discovered a sort of ‘vaccine’, however it will only work for the current outbreak. If the virus does get to your computer, perhaps through the opening of an email attachment, it first checks whether some other files are present on the computer, and if they are, then the virus shuts itself down and does no harm. So this is sort of like a kill switch.

I have sent a popup message to your computer to let you know that these vaccine files have been put in place on your computer, as well as to explain the patch situation above.