Recent Posts

2021-01-14

On development team metrics

 This article is pure gold:

https://teamplify.com/blog/why-you-shouldnt-rely-on-developer-metrics/

One of the very few articles that apart from saying that life is shit, actually tries to produce some suggestions on how to improve the situation and proposes other metrics to differentiate low and high IT R&D performers.

2020-12-03

Minimal operation desk clock - part 2 (end)

The hole idea is stupid, as this already exists:

https://de.braun-clocks.com/collections/analogue-clocks/products/bc07-classic-radio-controlled-european-analogue-alarm-clock-black-white

But I have more ideas to come :)

2020-11-20

Minimal operation desk clock - part 1 - vision

Time is priceless, time is money. Especially now, with COVID-19 roaming, when some of the lucky ones sitting at home on conference calls making money. So I need to watch time during these conference calls and the watch on my wrist nor the time measurement in the laptop I use are not enough. I need to see a big dials. And I do not want to set it up or maintain it. Just plug it in the power supply and let it run. 

So the features I need are:

  1. desk clock, 
  2. with dials, hour and minutes,
  3. I don't want to have to set the time manually. I need it to get the time from somewhere.
  4. Be DEAD PRECISE. +/- 5s is OK, but not more,
  5. running on some kind of power that I do not want to care about, wall socket or USB will have to do I guess.
Optional features:
  1. a seconds dial,
  2. date display.
Phase two:

  1. getting the power from a battery.
Phase three:
  1. finding out how can I power it without even charging it EVER.
So obviously getting a simple battery power desk clock for 3$ out of aliexpress is the obvious choice, but I won't be able to get Features 3 and 4. And there's little chance I'll ever get to phase three of the project. Let's do something that is less practical and much more expensive :)

Let's implement this idea in the following way:
  • arduino,
  • e-ink display,
  • wall socket or USB powered (for now),
  • some time source,
  • a case.
The time source: I do not want to use NTP or internet time. This would mean that I would need to get ethernet or some other network (wifi, BT) connectivity that will require setting up. I'll try to get time of GSM or radio stations :)

Next time - I'll try to understand the options I have with regards to time source and buy components. We'll see how it goes.


2019-06-29

Mac backups on Ubuntu 19.04 and Samba 4.10

Ubuntu 19.04 now contains samba 4.10, that should support all the SMB/CIFS extensions needed by MacOS to use the samba shares as TimeMachine storage. Tested with MacOS 10.14.5.

So let's do some TimeMachine backups on Ubuntu 19.04!

Assumptions:

  • your Ubuntu is running on some PC, with some fixed IP,
  • you have your Mac connected to the same network.

First install Samba:
apt install samba
Let's get the old samba config out of the way

mv /etc/samba/smb.conf /etc/samba/smb.confORG

Now create and edit /etc/samba/smb.conf (this is the same as in previous samba mac backups howto)

[global]
server role = standalone server
passdb backend = tdbsam
obey pam restrictions = yes
security = user
printcap name = /dev/null
load printers = no
socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=524288 SO_SNDBUF=524288
server string = Samba Server %v
dns proxy = no
wide links = yes
follow symlinks = yes
unix extensions = no
acl allow execute always = yes
# Special configuration for Apple's Time Machine
fruit:model = MacPro
fruit:advertise_fullsync = true
fruit:aapl = yes
fruit:time machine = yes
## Definde your shares here
[backup]
path = /space/backups
valid users = backups
writable = yes
durable handles = yes
kernel oplocks = no
kernel share modes = no
posix locking = no
vfs objects = catia fruit streams_xattr
ea support = yes
browseable = yes
read only = No
inherit acls = yes


Create and edit /etc/avahi/services/timemachine.service (this is the same as in previous samba mac backups howto)

<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">%h</name>
<service>
<type>_smb._tcp</type>
<port>445</port>
</service>
<service>
<type>_device-info._tcp</type>
<port>0</port>
<txt-record>model=RackMac</txt-record>
</service>
<service>
<type>_adisk._tcp</type>
<txt-record>sys=waMa=0,adVF=0x100</txt-record>
<txt-record>dk0=adVN=backup,adVF=0x82</txt-record>
</service>
</service-group>

Add the backup directory, backup user and set permissions on the directory. This also sets the password for SMB/CIFS access:

useradd -m backups
smbpasswd -a backups
mkdir -p /space/backups
chown backups /space/backups
chmod 700 /space/backups

Now either reboot your Ubuntu or restart avahi and samba.

And there, the new backup destination should show up in all macs connected to the same network. REMEMBER KIDS, DO ENCRYPTED BACKUPS!

ps. how to view you mac backups progress:

log stream --style syslog --predicate 'senderImagePath contains[cd] "TimeMachine"' --info

2018-05-12

How to get Mac High Sierra Time Machine backups working on an Ubuntu 18.04 server

There are lot's of howtos out there how to get Linux servers to support TimeMachine networked backups for Mac clients. But lately they all stopped working due to latest Mac High Sierra updates. Apple moves away from Netatalk protocol and recommends using SMB. Unfortunately the latest Samba you will get on Ubuntu 18.04 is 4.7, and this does not support so called fruit extensions needed by Mac to have Time Machine writing it's data to the destinations. We need to get Samba 4.8 that was released not so long ago.

So let's start. I'm assuming you do not have any other samba installed. The backup folder will pop up as "backup on <your linux server name>" and you will be using user name backups with the password you'll set on the way. I strongly recommend to read the howto I've posted at the end. It allows for a multi user setup.

Install samba:
sudo apt-get-repository ppa:linux-schools/samba-latest
sudo apt update
sudo apt install samba
This installs samba 4.8 that is a hard requirement to get SMB based TimeMachine backups working.

Let's get the old samba config out of the way
mv /etc/samba/smb.conf /etc/samba/smb.confORG
Now create and edit /etc/samba/smb.conf

[global]
server role = standalone server
passdb backend = tdbsam
obey pam restrictions = yes
security = user
printcap name = /dev/null
load printers = no
socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=524288 SO_SNDBUF=524288
server string = Samba Server %v
dns proxy = no
wide links = yes
follow symlinks = yes
unix extensions = no
acl allow execute always = yes
# Special configuration for Apple's Time Machine
fruit:model = MacPro
fruit:advertise_fullsync = true
fruit:aapl = yes
fruit:time machine = yes
## Definde your shares here
[backup]
path = /space/backups
valid users = backups
writable = yes
durable handles = yes
kernel oplocks = no
kernel share modes = no
posix locking = no
vfs objects = catia fruit streams_xattr
ea support = yes
browseable = yes
read only = No
inherit acls = yes

Create and edit /etc/avahi/services/timemachine.service

<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
 <name replace-wildcards="yes">%h</name>
 <service>
   <type>_smb._tcp</type>
   <port>445</port>
 </service>
 <service>
   <type>_device-info._tcp</type>
   <port>0</port>
   <txt-record>model=RackMac</txt-record>
 </service>
 <service>
   <type>_adisk._tcp</type>
   <txt-record>sys=waMa=0,adVF=0x100</txt-record>
   <txt-record>dk0=adVN=backup,adVF=0x82</txt-record>
 </service>
</service-group>
Create and edit /etc/rc.local as it looks like that samba 4.8 does not come with startup scripts.
#!/bin/bash
echo " # starting samba from rc.local"
smbd
exit 0
Add the backup directory, backup user and set permissions on the directory. This also sets the password for SMB/CIFS access:
useradd -m backups
smbpasswd -a backups
mkdir -p /space/backups
chown backups /space/backups
chmod 700 /space/backups
And let's start this (no reboot required):
/etc/init.d/avahi-daemon restart
smbd
And there, the new backup destination should show up in all macs connected to this network. REMEMBER KIDS, DO ENCRYPTED BACKUPS!

ps. how to view you mac backups progress:
log stream --style syslog --predicate 'senderImagePath contains[cd] "TimeMachine"' --info

Credits:
https://www.reddit.com/r/homelab/comments/83vkaz/howto_make_time_machine_backups_on_a_samba/

2017-06-26

Sim racing and game controllers - part 4 - Arduino leonardo project - TENSIOMETERS

Check the previous entries about the project: part1part2, part3 and the video and problems.

So I'm still using the Arduino racing pad since 2 years. I'm still racing in LFS, now in Assetto Corsa with it. I've complained about what's bad about it. And now I've solved another issue that I've had - the crappy joysticks. I've used FSR402 tensiometers for both accelerator and braking. This seems much more natural than using the lever sticks. And precise. Now I can drive powerful cars with no ABS and TC in Assetto Corsa :)

Why tensiometers?


When I've started thinking about that crappy joysticks, I've looked at what the game consoles are doing for the trigger buttons on the pads:

  • X360 pad uses a potentiometer with clever levers,
  • Playstation uses tensiometers,
  • X One uses Hall Effect sensors.
I wanted to buy the replacement parts for the X360 to check the levers, but the tensiometers are just cheaper. The Hall Effect sensors seem to be a very cool idea, but you really need to have an idea how to sort out the mechanics.

How does it look:

Bad. Ugly. But works.









I've placed the tensiometers along another edge of this beautiful lunch box. And now I can use both methods of controlling the speed of the car by just remapping controls. Frankly speaking - I haven't used the levers since I've got the tensiometers running.

Wiring FSR402 to Arduino:

Check this for examples of wiring and code: https://learn.adafruit.com/force-sensitive-resistor-fsr/using-an-fsr. After wiring the tensiometer properly you use it within the code like any other potentiometer.

Video:


Summary:

This just works. I'm using this for gaming weekly or biweekly (you know, 3 kids) for the last 3-4 months.

Using tensiometers for game controlers has another potential application. People making pedals for racing always look for methods to measure travel for acceleration and pressure for braking - to simulate real car hydraulics. All not ridiculously expensive steering wheels on the market use potentiometers for all pedals. And with a very simple mechanism (1 swing, some foam) you can get a pressure measuring tensiometer based pedal - you'll need a bigger tensiometer thou.

Code:

The requirements for having this running are described in the part3 of this "journey".

#include "HID-Project.h"

const int pinLed = LED_BUILTIN;
const int pinButton = 2;

// this is for printing to COM - set to 1 to get printouts
const int printuj = 0 ;

void setup() {
  pinMode(pinLed, OUTPUT);
  pinMode(pinButton, INPUT_PULLUP);
  Gamepad.begin();

  if ( printuj == 1 ) {
    Serial.begin(9600);
  }
}

void loop() {
  // limits for steering
  float steeringmin=0;
  float steeringmax=1023;
  // limits for joystick braking
  float brakemin=0;
  float brakemax=1023;
  // limits for joystick accelerating
  float accelmax=1023;
  // limits for tensometer acceleration and braking
  float brakemaxb=910;
  float accelmaxb=910;
  float accelmin=0;
  float min=-32767;
  float max=32767;
  float diff=max-min;
  float minB=-123;
  float maxB=+123;
  float diffB=maxB-minB;

  // steering
  float steer = (float)analogRead(0)/(steeringmax-steeringmin)*diff + min;

  // acceleration, braking for joysticks and for tensometers
  float accel = ((float)analogRead(2)/(accelmax-accelmin))*diff + min;
  float brake = ((float)analogRead(1)/(brakemax-brakemin))*diff + min;
  float accelb = ((float)analogRead(4)/(accelmaxb-accelmin))*diffB + minB;
  float brakeb = ((float)analogRead(3)/(brakemaxb-brakemin))*diffB + minB;

  // all 4 buttons readouts
  int gearup = digitalRead(2);
  int geardown = digitalRead(3);

  int gearupb = digitalRead(4);
  int geardownb = digitalRead(5);

  // idiotic deadzones for joystick
  if ((accel <= 3) and (accel >= -3)) {
    accel=0;
  }
  if ((brake <= 3) and (brake >= -3)) {
    brake=0;
  }

  // limits for tensometers
  if (accelb > maxB) {
    accelb=maxB;
  }
  if (brakeb > maxB) {
    brakeb=maxB;
  }

  // this is the COM printing
  if ( printuj == 1 ) {
        Serial.print ((int)steer);
        Serial.print (' ');
        Serial.print (analogRead(0));
        Serial.print (' ');
        Serial.print ((int)accel);
        Serial.print (' ');
        Serial.print (analogRead(2));
        Serial.print (' ');
        Serial.print ((int)brake);
        Serial.print (' ');
        Serial.print (analogRead(1));
        Serial.print (' ');
        Serial.print (gearup);
        Serial.print (' ');
        Serial.print (geardown);
        Serial.print (' ');
        Serial.print (gearupb);
        Serial.print (' ');
        Serial.print (geardownb);
                Serial.print (' ');
                Serial.print (analogRead(3));
                Serial.print (' ');
                Serial.print ((int)brakeb);
            Serial.print (' ');
                Serial.print (analogRead(4));
                Serial.print (' ');
                 Serial.print ((int)accelb);
        Serial.println (' ');
  }

 \\ button switching
 if (gearup == 0)
 {
   Gamepad.press(1);
 } else {
   Gamepad.release(1);
 }

 if (geardown == 0)
 {
   Gamepad.press(2);
 } else {
   Gamepad.release(2);
 }
 if (gearupb == 0)
 {
   Gamepad.press(3);
 } else {
   Gamepad.release(3);
 }

 if (geardownb == 0)
 {
   Gamepad.press(4);
 } else {
   Gamepad.release(4);
 }


 \\ output to axises. xA is 16bit, the rest I don't remember and it does not matter.
 Gamepad.xAxis((int)steer);
 Gamepad.yAxis((int)accel);
 Gamepad.rxAxis((int)brake);
 Gamepad.zAxis((int)accelb);
 Gamepad.rzAxis((int)brakeb);


 Gamepad.write();

}

Next step: getting some better chassis for the device.

2016-12-18

Headless linux google photos sync (nasty and dirty)

Intro

Google Photos is a marvelous service! You can store all of your photos for free (if you'd agree to compress them) and have them on the go on every device. It has it's downsides: sharing all photos to your wife is not an option and managing them (folders, mass actions, etc.) is not there. But hey, it comes at the low, low, low price of FREE.

Google did release a simple and effective tool for Mac and Windows that syncs all the photos you have available on your computer to their service. They did not release this for Linux. So people who have thousands of photos on their drives are left only with the possibility of dragging them to the browser window. And if you want to do this for 35000 images - this is going to be a wild ride.

Of course you can have a virtual machine with Windows and put the Google Sync Tool there, but let's ignore this option :) It needs at least 2G of ram and a Windows licence.

You can run the sync tool on Wine, as discussed here: https://www.reddit.com/r/linux/comments/37ptsw/any_got_the_new_google_photos_backup_desktop/, but you still run this manually and need X. If you wanted to run this on a server that you use to store all of your photos you were out of luck.

BUT NOT ANY MORE.

Ingredients:

Let's get the authentication key first

So just do what the howto mentioned above tells you to. You can use a friends Windows PC or download Windows ISO from Microsoft pages and run this as a trial under KVM or other virtualization solution of your choice. 

Install the Google Photos Sync Tool, fully authorize and export the regedit key that should contain the data below:
Location: HKEY_CURRENT_USER\Software\Google\Picasa\Picasa2\Preferences
[HKEY_CURRENT_USER\Software\Google\Picasa\Picasa2\Preferences]"GoogleOAuth"=hex:xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,\ xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx"GoogleOAuthEmail"="youremail@gmail.com""GoogleOAuthServices"="mail,lh2,cp,cp.manager,mailrelay,plus.stream.write,plus.circles.read,plus.profiles.read,plus.me,plus.media.upload,plus.media.readonly,plus.settings,youtube,""GoogleOAuthVersion"=dword:00000005
Get this file (lets call it gphotos.reg) to the server and you can delete the Windows virtual machine.

Let's install wine and prepare

We won't be needing X on the remote server, so login there with SSH and X forwarding:
ssh user@server -X
if you run now (remotely)
xclock
you should see the xclock window showing up on your workstation. If it does not you'd need to google to enable this, but this should work out of the box on most recent Linux distros.

Steps to be carried out:
  • install wine (as root)
sudo apt install wine
  • create a separate user for the sync tool (let's call it gphotos)
  • upload the sync tool exe and registry file from windows to the gphotos home directory
  • as the gphotos user start winecfg (using a remote SSH connection with X forwarding)
winecfg
  • switch the Windows version to Windows 7

Let's install Google Photos Sync Tool

Steps to be carried out:
  • simply run (using a remote SSH connection with X forwarding)
wine gpautobackup_setup.exe
  • proceed with default installation options until you will see that the installer is trying to open something up and it will just keep a blank white window open. (it tries to start up IE to let you log in to Google Photos),
  • kill the wine processes, shut the window
  • run regedit to install the gphotos.reg file and import
regedit
  • run the Google Photos Sync Tool again (but installed on your drive)
cd "/home/gphotos/.wine/dosdevices/c:/users/gphotos/Local Settings/Application Data/Programs/Google/Google Photos Backup"
wine "Google Photos Backup.exe"
  • it will now run from the moment after the authorization tool place and you will be able to select the folders you'd want to sync (be sure to check read permissions before this step).
  • finish, the sync tool started syncing your photos
Now the sync tool runs, but is still connected with your X session over SSH. Kill it and move on.

Start up at boot time

We'll be using xvfb-run, so be sure to make sure you have it on your system. This is used to start up a X session, without any X on the server.

  • Let's create a startup file for the service, located in /home/gphotos/gphotossync with the following contents:
cd "/home/gphotos/.wine/dosdevices/c:/users/gphotos/Local Settings/Application Data/Programs/Google/Google Photos Backup"xvfb-run -a -e /home/gphotos/log.log -s "-screen 0 1280x800x16" wine "Google Photos Backup.exe" & &>/tmp/gphotos.log

  • a few remarks here:
    • this assumes you did not customize any paths and run this as gphoto user,
    • -a makes xvfb-run select a display ID if the default one is busy,
    • /home/gphotos/log.log is a log for xfvb-run issues,
    • /tmp/gphotos.log for any issues wine might pop up with,
  • this script just runs the Google Photo Sync tool in the background and allows it to do it's job.
  • Let's just add this to the /etc/rc.local file, by adding the following line BEFORE the line with exit 0:
sudo -u gphotos -i /home/gphotos/gphotossync
  • and that's it. After reboot you should see your Google Photos Sync tool running and syncing photos.

Logs and monitoring

You might want to know what Google Photos Sync is actually doing, so:
  • you can see this in the process list or htop or other tools of choice if it is running or not,
  • you can access the logs to see what JPG files were processed when:
grep -i jpg "/home/gphotos/.wine/dosdevices/c:/users/gphotos/Local Settings/Application Data/Google/Google Photos Backup/network.log"
And that's it. I've managed to sync nearly 40 thousand family pictures, using Google's free Photos, from my Linux's server drive. If I add anything to the pictures folder, the Sync tool picks up straight away and uploads.

So good luck!