Category Archives: Computer

Mini DF MP3 player with MQTT control

Resistor is 1K, speaker is 4 ohm

I’ve got the DFPlayer with the GD3200B instead of the better YX5200, but it works.

As part of my game, so MQTT controlled.

First sound is low in volume.

Code

I’m using Soft Serial

// based on code from: 
// https://github.com/Makuna/DFMiniMp3/blob/master/examples/PlayMp3/PlayMp3.ino
// above example has no wifi/mqtt and is missing the SoftSerial include line
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiClient.h>
#include <DFMiniMp3.h>
#include "SoftwareSerial.h"
#include <Ethernet.h>

#define wifi_ssid "SSID"
#define wifi_password "SSIDPASS"
#define mqtt_server "MQTTSERVER"
#define mqtt_port 1883

WiFiClient espClient;
EthernetClient ethClient;
PubSubClient mqtt(espClient);

class Mp3Notify; 

SoftwareSerial secondarySerial(D6, D5); // RX, TX
typedef DFMiniMp3<SoftwareSerial, Mp3Notify> DfMp3;
DfMp3 dfmp3(secondarySerial);

class Mp3Notify
{
public:
  static void PrintlnSourceAction(DfMp3_PlaySources source, const char* action)
  {
    if (source & DfMp3_PlaySources_Sd) 
    {
        Serial.print("SD Card, ");
    }
    if (source & DfMp3_PlaySources_Usb) 
    {
        Serial.print("USB Disk, ");
    }
    if (source & DfMp3_PlaySources_Flash) 
    {
        Serial.print("Flash, ");
    }
    Serial.println(action);
  }
  static void OnError([[maybe_unused]] DfMp3& mp3, uint16_t errorCode)
  {
    // see DfMp3_Error for code meaning
    Serial.println();
    Serial.print("Com Error ");
    Serial.println(errorCode);
  }
  static void OnPlayFinished([[maybe_unused]] DfMp3& mp3, [[maybe_unused]] DfMp3_PlaySources source, uint16_t track)
  {
    Serial.print("Play finished for #");
    Serial.println(track);  

    // start next track
    track += 1;
    // this example will just start back over with 1 after track 3
    if (track > 3) 
    {
      track = 1;
    }
    dfmp3.playMp3FolderTrack(track);  // sd:/mp3/0001.mp3, sd:/mp3/0002.mp3, sd:/mp3/0003.mp3
  }
  static void OnPlaySourceOnline([[maybe_unused]] DfMp3& mp3, DfMp3_PlaySources source)
  {
    PrintlnSourceAction(source, "online");
  }
  static void OnPlaySourceInserted([[maybe_unused]] DfMp3& mp3, DfMp3_PlaySources source)
  {
    PrintlnSourceAction(source, "inserted");
  }
  static void OnPlaySourceRemoved([[maybe_unused]] DfMp3& mp3, DfMp3_PlaySources source)
  {
    PrintlnSourceAction(source, "removed");
  }
};

void setup_wifi() {
  delay(10);
  WiFi.mode(WIFI_STA);
  WiFi.begin(wifi_ssid, wifi_password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

void setup() 
{
  setup_wifi();
  mqtt.setServer(mqtt_server, mqtt_port);
  mqtt.setCallback(callback);
  Serial.begin(115200);
  Serial.println("initializing...");

  WiFiClient espClient;
  PubSubClient mqtt(espClient);

  mqtt.setClient(espClient);
  mqtt.setServer(mqtt_server, 1883);
    
  mqtt.setCallback(callback);
  mqtt.subscribe("escape/soundin");
  
  dfmp3.begin();

  uint16_t volume = dfmp3.getVolume();
  Serial.print("volume ");
  Serial.println(volume);
  dfmp3.setVolume(24);
  
  uint16_t count = dfmp3.getTotalTrackCount(DfMp3_PlaySource_Sd);
  Serial.print("files ");
  Serial.println(count);
  
  Serial.println("starting...");

  // start the first track playing
  // dfmp3.playMp3FolderTrack(1);  // sd:/mp3/0001.mp3
}

void reconnect() {
  // Loop until we're reconnected
  while (!mqtt.connected()) {
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (mqtt.connect(clientId.c_str())) {
      // Once connected, publish an announcement...
      mqtt.publish("escape", "sound connected");
      // ... and resubscribe
      mqtt.subscribe("escape/soundin");
    } else {
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}


void callback(char* topic, byte* payload, unsigned int length) {
    //  digitalWrite(led, HIGH);

    String topicStr = topic;
      byte value = atoi((char*)payload);
dfmp3.playMp3FolderTrack(value);  // sd:/mp3/0001.mp3
  Serial.println(value);
}

void waitMilliseconds(uint16_t msWait)
{
  uint32_t start = millis();

  while ((millis() - start) < msWait)
  {
    dfmp3.loop(); 
    delay(1);
  }
}

void loop() 
{
  
  if (!mqtt.connected()) {
    reconnect();
  }
    mqtt.loop();
  waitMilliseconds(100);
}

Wemos with Keypad, led and 7 segment display using MQTT

Warning, read the notes!

There are several caveats.

  • I was needing ALL GPIO pins, even RX/TX ( see trick below)
    When doing so, you can’t use serialprint.
    Do NOT enable, your sketch won’t work!
  • Don’t use pullup on D8, you can’t upload to the wemos if you do that
  • Due to library conflicts in keypad.h, DON’T change the order in the source. You will end up with compile errors!
  • The keypad has a weird pinout, but there are similar keypads with alternative layouts. Measure this using a multimeter.
  • The pull-up resistors will help fighting ghost key presses!
  • I2C needs D1/D2

To use RX/TX as GPIO pins you need to do the following:

//Define pins
  int led = 1; //tx
  int col = 3; //rx

// Change to function mode 3
// see https://www.esp8266.com/wiki/doku.php?id=esp8266_gpio_pin_allocations
  pinMode(1, FUNCTION_3);
  pinMode(3, FUNCTION_3);
 
// Revert to normal mode
// pinMode(1, FUNCTION0);

// Define mode input/output
// i'm using led to control the led so thats an output
// I'm using col for the keypad column scanner, that's an input
  pinMode(led, OUTPUT);
  pinMode(col, INPUT);

Complete code

The (*) clears input
The (#) sends the pin code using MQTT

Sending a 0 or 1 to escape/keypadin topic will toggle the led

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiClient.h>
// Do not change order!
#include "Keypad.h"
#include <TM1637Display.h>
#include <Ethernet.h>

#define wifi_ssid "SSID"
#define wifi_password "SSIDPASS"
#define mqtt_server "MQTTSERVER"
#define mqtt_port 1883

#define MSG_BUFFER_SIZE  (50)
char msg[MSG_BUFFER_SIZE];
int value = 0;

const byte ROWS = 4; //four rows
const byte COLS = 3; //four columns

int led = 1; //tx
int col = 3; //rx

#define CLK D1
#define DIO D2
#define TEST_DELAY   2000
TM1637Display display(CLK, DIO);

char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
byte rowPins[ROWS] = {D3, D5 , D6 , D7 };
byte colPins[COLS] = {D4 , col, D8 };

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
int keyNum = 0;
WiFiClient espClient;
EthernetClient ethClient;

PubSubClient mqtt(espClient);

void setup_wifi() {
  delay(10);
  WiFi.mode(WIFI_STA);
  WiFi.begin(wifi_ssid, wifi_password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}


void setup() {
  setup_wifi();
  mqtt.setServer(mqtt_server, mqtt_port);
  mqtt.setCallback(callback);
  
  pinMode(1, FUNCTION_3);
  pinMode(3, FUNCTION_3);
  pinMode(led, OUTPUT);
  pinMode(col, INPUT);
  // using above? .. then disable serial!
  // Serial.begin(9600);
display.showNumberDec(0, true);
delay(TEST_DELAY);
WiFiClient espClient;
PubSubClient mqtt(espClient);

 mqtt.setClient(espClient);
 mqtt.setServer(mqtt_server, 1883);
    
mqtt.setCallback(callback);
mqtt.subscribe("escape/keypadin");

}

void callback(char* topic, byte* payload, unsigned int length) {
    //  digitalWrite(led, HIGH);

    String topicStr = topic;
      byte value = atoi((char*)payload);
       if (value == 1){
    digitalWrite(led, HIGH);

 }else if (value == 0){
    digitalWrite(led, LOW);
 }
    

}

void reconnect() {
  while (!mqtt.connected()) {
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    if (mqtt.connect(clientId.c_str())) {
      mqtt.publish("outTopic", "hello world");
      mqtt.subscribe("escape/keypadin");
    } else {
      delay(5000);
    }
  }
}



void loop() {

  if (!mqtt.connected()) {
    reconnect();
  }
    mqtt.loop();

  // put your main code here, to run repeatedly:
  char key = keypad.getKey();

  if (key) {

    if(key=='*'){
      keyNum = 0;
    } else if (key=='#'){
         ++value;
  snprintf (msg, MSG_BUFFER_SIZE, "#%1d", keyNum);
        mqtt.publish("escape/keypad", msg);
    }
    
       else{
      if(keyNum<=999){
        keyNum = (keyNum*10) + (int(key)-48);
      }
    }
    
    //  Serial.println(key);
    display.setBrightness(0x0f);

    uint8_t data[] = { 0x0, 0x0, 0x0, 0x0 };
    display.setSegments(data);

    display.setSegments(data);
    display.showNumberDec(keyNum);

  }

}

Scraping authenticated websites

A friend needed to scrape data from an authenticated website.
This needs to be scripted and processed without human intervention.

Following steps are needed to get the correct curl commands (one time only)

Login page
Press F12 or right-click inspect
Click network and reload using ctrl-r
Select the start page and right click
copy as cURL (bash)

next steps

save curl command in a file

remove –compresssion and -H ‘Cookie: JSESSIONID=?????????????????????????????’

add just after curl

-k (no certificate check) and
–cookie-jar tmpcookiefile

excecute this. It will give you a file with a session id and a true field.
(This will change at every login)
but is needed for subsequential requests

Next: use this sessioncookie to get the next authenticated request

So to scrape with login, you need two lines in your script.
One to get the session cookie. (YOUR username/pass will be in here!!)
And the second to get the needed page using the cookie

#!/bin/bash
#authenticate and save sessioncookie
curl -k --cookie-jar part1.cookie 'https://xxx.xxxxx.xxx/site/dologin'   -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7'   -H 'Accept-Language: en-GB,en;q=0.9,nl-NL;q=0.8,nl;q=0.7'   -H 'Cache-Control: max-age=0'   -H 'Connection: keep-alive'   -H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryb1chvkAVZSF3hPSu'    -H 'Origin: https://xxx.xxxxx.xxx'   -H 'Referer: https://xxx.xxxxx.xxx/site/loginform'   -H 'Sec-Fetch-Dest: document'   -H 'Sec-Fetch-Mode: navigate'   -H 'Sec-Fetch-Site: same-origin'   -H 'Upgrade-Insecure-Requests: 1'   -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36'   -H 'sec-ch-ua: "Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"'   -H 'sec-ch-ua-mobile: ?0'   -H 'sec-ch-ua-platform: "Windows"'   --data-raw $'------WebKitFormBoundaryb1chvkAVZSF3hPSu\r\nContent-Disposition: form-data; name="form[username]"\r\n\r\nusername\r\n------WebKitFormBoundaryb1chvkAVZSF3hPSu\r\nContent-Disposition: form-data; name="form[password]"\r\n\r\npassword\r\n------WebKitFormBoundaryb1chvkAVZSF3hPSu\r\nContent-Disposition: form-data; name="form[refname]"\r\n\r\n\r\n------WebKitFormBoundaryb1chvkAVZSF3hPSu\r\nContent-Disposition: form-data; name="form[refid]"\r\n\r\n\r\n------WebKitFormBoundaryb1chvkAVZSF3hPSu\r\nContent-Disposition: form-data; name="form[refmod]"\r\n\r\n\r\n------WebKitFormBoundaryb1chvkAVZSF3hPSu\r\nContent-Disposition: form-data; name="form[csrf_hash]"\r\n\r\ncsrf_ab09f7887d9dacfe1489b68b64fe6a01\r\n------WebKitFormBoundaryb1chvkAVZSF3hPSu--\r\n'
#get data from second page
curl -k -l --cookie part1.cookie  https://xxx.xxxxx.xxx/subscriber/overview

Mikrotik and Home Assistant

A friend of mine remembered me of the Mikrotik addons in HA.
I forgot all about this.

I’ve got two integrations running. (Installed via HACS)

Don“t forget to enable the API on your devices.

/ip services
set api disabled=no port=8728

The addons/integrations extract a lot of information from the MT devices.

This integration will also let you know that your MT Router can be updated.

This is part if the presence detector/Device locator.
My roaming wifi network will give false locations. My laptop never left the same spot!

I will add to this page, after testing for a while

DNS / DHCP

Today i’ve migrated my DNS/DHCP to a Mikrotik router.
See post

I’m planning to replace my main firewall/dhcp/dns/web/irc/mail/ids whatever more .. to virtual machines and a mikrotik router.

Having used bind and isc-dhcp-server for many years, i had to try some alternatives.

  • DNS in FreeIPA
  • Unbound with zone/dns
  • Phpipam with powerdns

And now DNS/DHCP in a Mikrotik router!

I still use Phpipam as cmdb.
So i’m planning to use ansible to synchronize phpipam and the mikrotik.

Nice .. no seach domain needed …
nslookup webserver, resolves webserver.dmz
If there are 2 hosts with the same hostname, you have to add a domain.

Shelly Devices

I love shellies, easy to implement and hacker friendly.

MQTT out of the box.
Curl in and out – you can switch it on/off using curl, but it can send a http command also.
I’ve used this with Domoticz and Home Assistant.
It has a webinterface, with timers, and there is also a client for Android/Iphone
You’ve got some own gpio pins to your disposal and the unit is flash-able!

curl -X POST https://shellydevice/device/relay/control -d "channel=IDHERE&turn=on&id=ID&auth_key=AUTH"

The device is not isolated from the mains. To flash it, the mains must be disconnected.

SHELLY 1

I use this for simple on/off switches around the house.
Using it with a physical switch and MQTT (Nodered)

SHELLY 2 PM

Same as above but this one has a build in power meter

SHELLY DIMMER

Generic dimmer

Dimmer with low voltage rotary encoder!
https://www.instructables.com/Shelly-Dimmer-Wall-Switch-With-Rotary-Knob-and-Hom/

SHELLY RGBW2

A RGBW / 4 Channel controller
You can connect RGB strips, but also dimmable white strips in 4 channels. 12V or 24V.
NOTE! : There is a common 12V connection, and GND will be controlled!

SHELLY PLUG S

I love these small wall plugs, i’ve used these also to find power consuming devices around the house.

For example, i made a nodered flow, to see if the washing machines are running or not.

SHELLY BUTTON

This became my all purpose alarm thinghy

SHELLY DOORSENSOR

A door sensor WITH temperature and light sensor build in!

Home Assistant example

SHELLY WATER SENSOR

This one lays below our washing machine

SHELLY SMOKE ALARM

(Preordered)

SHELLY PM4

A four channel power measure/switch for your fuse box


GENERIC SHELLY STUFF
A smart doorbell schematic i found

https://www.thingiverse.com/thing:5756154
Very nice .. printable cases for your shellies!

Converting old media

Old files, own created stuff, downloaded stuff. Sometimes there are no viewers anymore, or you thrown devices away.

(I will add to this when i find more information)

These are the tools i’ve used to convert them to a newer format.

NOTE: Converting will always impact the quality

IMAGES

LBM (amiga)

ilbmtoppm < test.LBM | pnmtopng - > test.png

RAM (video files)

ffmpeg -i file.ram file.mp4
or
ffmpeg -i file.ram file.gif

Own DVD’s
NOTE: VOB files are mpg, to keep same quality i use stream copy (-c copy) , besides mpg i“d like to have movies in a web streamable format like MP4, so i DO convert these

ffmpeg -i "concat:VTS_01_1.VOB|VTS_01_2.VOB|VTS_01_3.VOB" -f mpeg -c copy output.mpeg

Flash/SWF

http://www.swffileplayer.com/
https://flasharch.com/en/downloads
.. and record with OBS

AMR ( Adaptive Multi-Rate audio codec )

ffmpeg -i folkband.amr -ar 22050 folkband.mp3

3GP

ffmpeg -i pipes.3gp -vcodec h264 -c:a aac pipes.mp4
If your 3gp is recent and has a x264 tag (check with mediainfo)
then you can convert lossless with
ffmpeg -i 10026202.3gp -c:v copy -c:a copy 10026202.mp4

QTVR (need to get a better solution for this)
I’ve used this for rendered scenes

ffmpeg -i ../test.mov %02d.png
ffmpeg -i %02d.png -vf "tile=1x24,transpose=1" qtvrmovie.png

FLV

ffmpeg -i filename.flv -c:v libx264 -crf 19 -strict experimental filename.mp4

WEBP (Not a old media format, but i dont like webp format.)
This script converts to images or animated gif depending on the number of frames

#!/bin/bash


ls *webp |  while read file; do
duration=$(webpinfo -summary "$file" | grep Duration | head -1 |  sed -e 's/.* \([0-9]*\)$/\1/')
frames=$(webpinfo -summary "$file" | grep frames | head -1 |  sed -e 's/.* \([0-9]*\)$/\1/')
if [ "$duration" == "0" ] ; then duration=50 ;fi
echo "DUR $duration : FRM $frames"
dur=$( echo "$duration / 100" | bc )


if [ $frames == "1" ] ; then convert $file png/$file.jpg 
else 
for i in $(seq -f "%05g" 1 $frames)
do
    webpmux -get frame $i $file -o $file.$i.webp
    dwebp $file.$i.webp -o $file.$i.png
done
fi

convert $file.*.png  -colorspace srgb  +dither  -delay $dur -loop 0 gif/$file.gif
rm $file.[0-9]*.png *webp.[0-9]*.webp
done

Nextcloud Notes

(Old and new notes, i will keep adding info)

A install step stopped .. find a .step file and remove this

[nginx@nextcloud nextcloud]$ rm /mnt/fileserver/updater-ocv0dxmv6vpg/.step

Login page loop: directory rights wrong

This server was running nginx
drwxrwx---.  2 root apache     6 Jan  3 18:19 wsdlcache
drwxrwx---.  2 root apache 16384 Jan  3 18:19 session
drwxrwx---.  2 root apache     6 Jan  3 18:19 opcache

fixed with:
chown root:nginx /var/lib/php/session 
chown root:nginx /var/lib/php/opcache
chown root:nginx /var/lib/php/wsdlcache

Other things to check (Generic)

  • Really slow storage can cause problems, check with iotop
  • Check selinux! (temporary test with : setenforce 0 )
  • Behind a reverse proxy? remove these options in your config.php and check a local connection. This is a test for: reverseproxy, firewall and proxy settings in config.php. Need to test a localhost connection with your browser?
    ssh -L8080:localhost:80 nextcloudserver (and connect to http://localhost:8080 with your browser
  • Check your services! .. memcache, nginx, apache, mysql/mariadb
  • Check logs: journalctl -f, tail -f /var/log/nginx/*log /x/y/z/netcloud.log
  • Storage on a remote server? (Using NFS for example) Check your rights
    • change into your webserver account and test access to files.storage
      ( sudo su – nginx -s /bin/bash )

Migrating users to a complete new nextcloud instance keeping IDs

Get a list of users

su - apache -s /bin/bash  -c " source /opt/rh/rh-php72/enable; cd /var/www/html/nextcloud ;./occ user:list 2>/dev/null | grep -v admin ; exit" > listofusers

Sync and check users
Rsync data and use occ command to scan files into database

#!/bin/bash
cd /root
#set -x
templist=templist.$$
./getlistusers > userlistsvr1
cat userlistsvr1 > /tmp/$templist
cat userlistsvr2.new >> /tmp/$templist
cat /tmp/$templist | cut -f2 -d: | sort  | uniq -c | grep " 2 " | cut -c 10- > /tmp/deze.$$
cat /tmp/deze.$$ | while read ; do
	echo "User $REPLY"
	oldtest=0
	newtest=0
	old=$(cat userlistsvr2 | grep "$REPLY" | awk '{ print $2 }' | sed s/://g)
	new=$(cat userlistsvr1 | grep "$REPLY" | awk '{ print $2 }' | sed s/://g)
	test -d /var/data/owncloud/data/$old/files/ && oldtest=1
	test -d /var/data/owncloud/nextcloud/$new/files/ && newtest=1
	if [ $oldtest -eq 1 ] ; then echo " found old dir - $old" ; fi
	if [ $newtest -eq 1 ] ; then echo " found new dir - $new" ; fi
	if [ $oldtest -eq 1 ] && [ $newtest -eq 1 ] ; then echo "  both found - ready to sync" 
		rsync -va /var/data/owncloud/data/$old/files/ /var/data/owncloud/nextcloud/$new/files/
		echo " RUN occ files:scan $new ############################"
		su - apache -s /bin/bash  -c " source /opt/rh/rh-php72/enable; cd /var/www/html/nextcloud ;./occ files:scan $new"
        fi
	echo " "
 
done
rsync -va  /var/data/owncloud/data/root/files/xyz/ /var/data/owncloud/nextcloud/38842e24-5d0d-11e9-dbdb-0001a4ab950f/files/
su - apache -s /bin/bash  -c " source /opt/rh/rh-php72/enable; cd /var/www/html/nextcloud ;./occ files:scan 38842e24-5d0d-11e9-dbdb-0001a4ab950f"

Linux crypt methods i’m using.

Some directories on my fileserver are encrypted using ecryptfs.

eCryptfs is a POSIX-compliant enterprise cryptographic stacked filesystem for Linux. eCryptfs stores cryptographic metadata in the header of each file, so that encrypted files can be copied between hosts; the file will be decrypted with the proper key in the Linux kernel keyring. There is no need to keep track of any additional information aside from what is already in the encrypted file itself. You may think of eCryptfs as a sort of “gnupg as a filesystem”.

Example crypted directory using filename encryption

ECRYPTFS_FNEK_ENCRYPTED.FWYQ.y58tWRY7EQqyVPxxMk11BuiLpk8jXCQ8BRz0z5p9C2Pu2HZg-mmv---/ECRYPTFS_FNEK_ENCRYPTED.FWYQ.y58tWRY7EQqyVPxxMk11BuiLpk8jXCQ-Jx6RlQrLhDhdZ9IrcCOAE--
ECRYPTFS_FNEK_ENCRYPTED.FWYQ.y58tWRY7EQqyVPxxMk11BuiLpk8jXCQ8BRz0z5p9C2Pu2HZg-mmv---/ECRYPTFS_FNEK_ENCRYPTED.FWYQ.y58tWRY7EQqyVPxxMk11BuiLpk8jXCQ.cE4XNdvLLui2EamsqU2rE--
ECRYPTFS_FNEK_ENCRYPTED.FWYQ.y58tWRY7EQqyVPxxMk11BuiLpk8jXCQ8BRz0z5p9C2Pu2HZg-mmv---/ECRYPTFS_FNEK_ENCRYPTED.FWYQ.y58tWRY7EQqyVPxxMk11BuiLpk8jXCQ1J..MuVpsw6kaCgwYCwJXk--

Adhoc mounting

You can use the same dir for mounting!
Filenames are encrypted also.
Use umount go back to the crypted state

NOTE: You can write files to the crypted dir, if you are NOT using filename encryption, you can’t see which one is crypted and which is not.
Use the script below to get hints of the readable files!

mount -t ecryptfs securedir securedir
Passphrase:
Select cipher:
 1) aes: blocksize = 16; min keysize = 16; max keysize = 32
 2) blowfish: blocksize = 8; min keysize = 16; max keysize = 56
 3) des3_ede: blocksize = 8; min keysize = 24; max keysize = 24
 4) twofish: blocksize = 16; min keysize = 16; max keysize = 32
 5) cast6: blocksize = 16; min keysize = 16; max keysize = 32
 6) cast5: blocksize = 8; min keysize = 5; max keysize = 16
Selection [aes]:
Select key bytes:
 1) 16
 2) 32
 3) 24
Selection [16]:
Enable plaintext passthrough (y/n) [n]:
Enable filename encryption (y/n) [n]: y
Filename Encryption Key (FNEK) Signature [xxxxxxxxxxxxxxxxxx]:
Attempting to mount with the following options:
  ecryptfs_unlink_sigs
  ecryptfs_fnek_sig=xxxxxxxxxxxxxxxxxx
  ecryptfs_key_bytes=16
  ecryptfs_cipher=aes
  ecryptfs_sig=xxxxxxxxxxxxxxxxxxx
Mounted eCryptfs

Crypting disks for travel/backup

For this i’m using Luks

The Linux Unified Key Setup (LUKS) is a disk encryption specification created by Clemens Fruhwirth in 2004 and was originally intended for Linux.

While most disk encryption software implements different, incompatible, and undocumented formats , LUKS implements a platform-independent standard on-disk format for use in various tools. This not only facilitates compatibility and interoperability among different programs, but also assures that they all implement password management in a secure and documented manner

Formatting a disk and mounting

cryptsetup luksFormat /dev/sdb1

WARNING!
========
This will overwrite data on /dev/sdb1 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase for /dev/sdb1:
Verify passphrase:
root@workstation:~# cryptsetup luksOpen /dev/sdb1 crypto
Enter passphrase for /dev/sdb1:
root@workstation:~# mkfs.ext4 /dev/mapper/crypto
mke2fs 1.44.1 (24-Mar-2018)
Creating filesystem with 244188672 4k blocks and 61054976 inodes
Filesystem UUID: 844eb9ee-d4da-4dfd-9d94-b62987e96b93
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
        102400000, 214990848

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

root@workstation:~# mount /dev/mapper/crypto /backup/

Umount and close

umount /backup
cryptsetup luksClose crypto

File crypt checker (checks for data files which COULD be crypted)

#!/bin/bash
find secure -type f  -exec file {} \;| egrep -v "ASCII text|MS Windows shortcut|ISO-8859 text|image data|PDF document|PC bitmap|Composite Document File|WebM|ISO Media|Microsoft Word|HTML| Microsoft Excel|Matroska|vCard|Microsoft ASF|Web/
P|RIFF|MPEG|RealMedia|UTF\-8 Unicode|Zip archive data|Macromedia Flash|RAR archive|EPUB document|Adobe Photoshop Image|AppleDouble|OpenType|empty|gzip compressed data|MS Windows|OpenDocument|Paint Shop Pro|executable|PostScript document|
Rich Text|audio data|SVG Scalable|UDF filesystem|very short file|Web Open Font Format|IFF |TrueType|BeautifulWatches|MTS:" > data-or-not

OR 

File crypt checker ( When the directory is in crypted state )
All files should be raw data

#!/bin/bash
find secure -type f  -exec file {} \;| egrep -v data$  > notcrypted-files

Escape game messages screen v1

Today working on the backend engine and screens like this.
All text will be generated, and send from the server.

A local version to try in your browser: (optimized for 1920×1080 press F11!)

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Indie+Flower&family=Tangerine&display=swap" rel="stylesheet">

<style>

body {
    background: url("background.jpg");
    height: 1080px;
    width: 100%;
    text-align: center;
    margin: auto;
    font-family: 'Tangerine', cursive;
    color:#000;
	}
/* The Modal (background) */
.modal {
  display: none; /* Hidden by default */
  position: fixed; /* Stay in place */
  z-index: 1; /* Sit on top */
  padding-top: 100px; /* Location of the box */
  left: 0;
  top: 0;
  width: 100%; /* Full width */
  height: 100%; /* Full height */
  overflow: auto; /* Enable scroll if needed */
  background-color: rgb(0,0,0); /* Fallback color */
  background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}

/* Modal Content */
.modal-content {
  background-image: url("note.jpg"); /* The image used */
  height: 788px; /* You must set a specified height */
  background-position: center; /* Center the image */
  background-repeat: no-repeat; /* Do not repeat the image */
  margin: auto;
  padding: 20px;
}

/* The Close Button */
.close {
 position: absolute; /*Can also be `fixed`*/
  color: #ff0000;
  		  font-size: 40px;
		  right: 550px;

  font-weight: bold;
}

.close:hover,
.close:focus {
  color: #000;
  text-decoration: none;
  cursor: pointer;
}
.topcontent {
        width: 400px;
        height: 200px;
        font-family: 'Indie Flower', cursive;
		  font-size: 40px;

        position: absolute; /*Can also be `fixed`*/
        left: 0;
        right: 350;
        top: -440;
        bottom: 0;
        margin: auto;
        /*Solves a problem in which the content is being cut when the div is smaller than its' wrapper:*/
        max-width: 100%;
        max-height: 100%;
        overflow: auto;
}
.playercontent {
        width: 400px;
        height: 200px;
        font-family: 'Indie Flower', cursive;
		  font-size: 40px;

        position: absolute; /*Can also be `fixed`*/
        left: 0;
        right: 300;
        top: -340;
        bottom: 0;
        margin: auto;
        /*Solves a problem in which the content is being cut when the div is smaller than its' wrapper:*/
        max-width: 100%;
        max-height: 100%;
        overflow: auto;
}
.content {
        width: 400px;
        height: 200px;
        font-family: 'Indie Flower', cursive;
		  font-size: 40px;

        position: absolute; /*Can also be `fixed`*/
        left: 0;
        right: 0;
        top: 100;
        bottom: 0;
        margin: auto;
        /*Solves a problem in which the content is being cut when the div is smaller than its' wrapper:*/
        max-width: 100%;
        max-height: 100%;
        overflow: auto;
}
</style>
</head>
<body>


<!-- Trigger/Open The Modal -->
<button id="myBtn">Incoming message</button>

<!-- The Modal -->
<div id="myModal" class="modal">
  <div class="topcontent">HQ</div>
  <div class="playercontent">Spy #1</div>

  <div class="content">We need the code now! Look for a yellow key</div>

  <!-- Modal content -->
  <div class="modal-content">
  
    <span class="close">close</span>
  </div>

</div>

<script>
// Get the modal
var modal = document.getElementById("myModal");

// Get the button that opens the modal
var btn = document.getElementById("myBtn");

// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];

// When the user clicks the button, open the modal 
btn.onclick = function() {
  modal.style.display = "block";
}

// When the user clicks on <span> (x), close the modal
span.onclick = function() {
  modal.style.display = "none";
}

// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
  if (event.target == modal) {
    modal.style.display = "none";
  }
}
</script>