Computer Stuff

mbr2gpt cannot find os partition(s)

Cloned a disk to ssd. It’s MBR / BIOS based.

Target system is EFI only.

Trying to do mbr2gpt but mbr2gpt not happy because I chose not to clone the partition that held the BIOS/legacy boot files.

Bit of a chicken and egg situation.
mbr2gpt can’t find MBR/BIOS stuff to convert from, and bcdboot /s won’t install MBR/BIOS stuff because the environment is EFI.

solution:

bcdboot c:\windows /f bios /s c:

..then..
mbr2gpt /convert /disk:0

TTF to ZPL font conversation and downloading to RAM with Python. Honeywell/Intermec labels.

With some LLM help, this works a treat. No need to pre-download fonts to the printers. Custom fonts galore!

As a test, it dumps the Z64 encoded data to the console, and sends to a printer on port 9100.

import os
import binascii
import socket
import zlib
import base64
from typing import Optional

def font_to_zpl(dir_path: str, font_name: str) -> str:
    """
    Convert a font file to a ZPL command string with Z64 encoding.
    
    Args:
        dir_path (str): Directory path where the font file is located
        font_name (str): Name of the font file (e.g., 'comic.ttf')
    
    Returns:
        str: ZPL command string containing the font data
    """
    # Construct the full file path
    file_path = os.path.join(dir_path, font_name)
    
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"Font file '{font_name}' not found in '{dir_path}'")

    with open(file_path, 'rb') as file:
        font_bytes = file.read()
    
    # Compress the data using zlib's DEFLATE (LZ77) algorithm
    compressed_data = zlib.compress(font_bytes)

    # Encode the compressed data in Base64
    base64_encoded_data = base64.b64encode(compressed_data).decode('utf-8')

    # Calculate CRC32 of the Base64-encoded data
    crc_value = zlib.crc32(base64_encoded_data.encode('utf-8')) & 0xFFFF
    crc_hex = f"{crc_value:04X}".lower()  # Format as 4 lowercase hex digits

    # Create the Z64-encoded font data string with CRC
    encoded_data_with_crc = f":Z64:{base64_encoded_data}:{crc_hex}"

    # Get the original font size (in bytes) for the `~DY` command
    original_size = len(font_bytes)

    # Construct the ZPL command to send to the printer
    zpl = (
        f"^XA\n"
        f"~DUR:{font_name.upper()},{original_size},{encoded_data_with_crc}\n"
        f"^FB1200,1,,C,"
        f"^CW1,R:{font_name.upper()}\n"
        f"^FO20,20"
        f"^A@N,40,,R:{font_name.upper()}\n"
        f"^FDThis is {font_name}!^FS\n"
        f"^XZ"
    )
    
    return zpl

def send_to_device(host: str, port: int, data: str, timeout: Optional[float] = 5.0) -> bool:
    """
    Send data to a device over TCP.
    
    Args:
        host (str): The IP address or hostname of the device
        port (int): The port number (typically 9100 for printers)
        data (str): The data to send
        timeout (float, optional): Socket timeout in seconds. Defaults to 5.0
    
    Returns:
        bool: True if successful, False if failed
    """
    try:
        # Create a TCP socket
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            # Set timeout
            sock.settimeout(timeout)
            
            # Connect to the device
            sock.connect((host, port))
            
            # Send the data
            sock.sendall(data.encode('utf-8'))
            
            return True
            
    except socket.timeout:
        print(f"Error: Connection to {host}:{port} timed out")
        return False
    except ConnectionRefusedError:
        print(f"Error: Connection to {host}:{port} was refused")
        return False
    except Exception as e:
        print(f"Error sending data to {host}:{port}: {str(e)}")
        return False

def main():
    # Configuration
    dir_path = r"C:\Users\CarlFarrington\envs\zpltest\ttf"  # Replace with your directory path
    font_name = "AndaleM.ttf"
    device_ip = "192.168.1.47"  # Replace with your device's IP address
    device_port = 9100
    
    try:
        # Generate ZPL command
        zpl_command = font_to_zpl(dir_path, font_name)
        
        # Print the command (for debugging)
        print("Generated ZPL command:")
        print(zpl_command)
        
        print("\nSending to device...")
        # Send to device
        if send_to_device(device_ip, device_port, zpl_command):
            print(f"Successfully sent to {device_ip}:{device_port}")
        else:
            print("Failed to send data to device")
            
    except FileNotFoundError as e:
        print(e)
    except Exception as e:
        print(f"Error: {str(e)}")

if __name__ == "__main__":
    main()

Patton SmartNode SN 4112 or 4114 FXO with Yealink DECT phone

This config is to allow a Yealink W70B / W56H DECT phone to register as ‘101’, and then place and receive calls via the PSTN (using port fxo 0 0). It’s useful while waiting for number ports (PSTN to SIP provider) to complete instead of putting PSTN on call-divert, and in my case I actually just want to install the SIP-only DECT phone and leave the copper line in place for now. I am aware of the Gigaset N300IP (combined SIP and POTS) but those don’t support PoE. This will allow me to put the W70B PoE DECT base in a good central location and still use the POTS line.

I spent an afternoon trying to figure out why the location service wasn’t working. I could see that directing PSTN to IF_SIP worked, but IF_SIP didn’t know where to send the call. Directing it to the location service didn’t work and there was nothing at all in the syslog. It turns out I needed the mapping function to rewrite the called_nr to 101 so that it would match the registered identity in the location service.

Also, outgoing calls do not work with dial-after dialtone. I had to use dial-after timeout 1. However I was using an ATA to simulate a PSTN line at home so YMMV. Ignore that. When I connected to a real line, the default dial-after dialtone worked fine.

You should update the password to something strong.
That’s this bit here:
authentication-service SER_AUTH
realm 1 smartnode-gw
username 101 password 101



#----------------------------------------------------------------#
#                                                                #
# SN4112/JO/EUI                                                  #
# R6.11 2019-07-02 H323 SIP FXS FXO                              #
# 2024-08-09T18:47:19                                            #
# SN/00A0BA0BD2B7                                                #
# Generated configuration file                                   #
#                                                                #
#----------------------------------------------------------------#

cli version 3.20

clock local default-offset +00:00
webserver port 80 language en
sntp-client
sntp-client server primary uk.pool.ntp.org port 123 version 4

system

  ic voice 0
    low-bitrate-codec g729

profile ppp default

profile call-progress-tone UK_Dialtone
  play 1 5000 350 -13 440 -13

profile call-progress-tone UK_Alertingtone
  play 1 400 400 0 450 0
  pause 2 200
  play 3 400 400 0 450 0
  pause 4 2000

profile call-progress-tone UK_Busytone
  play 1 375 400 0
  pause 2 375

profile call-progress-tone UK_CongestionTone
  play 1 400 400 0
  pause 2 350
  play 3 225 400 0
  pause 4 525

profile call-progress-tone UK_WaitingTone
  play 1 100 400 0
  pause 2 5000

profile call-progress-tone UK_ReleaseTone
  play 1 1500 400 0

profile tone-set default
profile tone-set UK
  map call-progress-tone dial-tone UK_Dialtone
  map call-progress-tone ringback-tone UK_Alertingtone
  map call-progress-tone busy-tone UK_Busytone
  map call-progress-tone waiting-tone UK_WaitingTone
  map call-progress-tone release-tone UK_ReleaseTone
  map call-progress-tone congestion-tone UK_CongestionTone

profile voip default
  codec 1 g711alaw64k rx-length 20 tx-length 20 silence-suppression
  codec 2 g711ulaw64k rx-length 20 tx-length 20 silence-suppression
  no high-pass-filter

profile pstn default
  echo-canceler-hybrid-loss 9

profile sip default
  no autonomous-transitioning

profile aaa default
  method 1 local
  method 2 none

context ip router

  interface eth0
    ipaddress dhcp
    tcp adjust-mss rx mtu
    tcp adjust-mss tx mtu

context cs switch
  national-prefix 0
  international-prefix 00

  routing-table called-e164 RT_FROM_PSTN
    route default dest-service SIP_LOC_SER MAP_CALLED_NR_101

  mapping-table called-e164 to called-e164 MAP_CALLED_NR_101
    map "" to 101

  interface sip IF_SIP
    bind context sip-gateway GW_SIP
    route call dest-interface IF_PSTN_00
    early-disconnect
    use profile tone-set UK

  service sip-location-service SIP_LOC_SER
    bind location-service SER_LOCATION

  interface fxo IF_PSTN_00
    route call dest-table RT_FROM_PSTN
    loop-break-duration min 80 max 300
    disconnect-signal loop-break
    use profile tone-set UK

context cs switch
  no shutdown

authentication-service SER_AUTH
  realm 1 smartnode-gw
  username 101 password 101

location-service SER_LOCATION
  domain 1 smartnode-gw
  match-any-domain

  identity-group default

    registration inbound
      lifetime default 3600 min 1 max 4294967295

  identity 101 inherits default
    display-name 101

    authentication inbound
      authenticate 1 authentication-service SER_AUTH username 101

    registration inbound
      lifetime default 3600 min 1 max 4294967295

context sip-gateway GW_SIP

  interface WAN
    bind interface eth0 context router port 5060

context sip-gateway GW_SIP
  bind location-service SER_LOCATION
  no shutdown

port ethernet 0 0
  medium auto
  encapsulation ip
  bind interface eth0 router
  no shutdown

port fxo 0 0
  use profile fxo gb
  encapsulation cc-fxo
  bind interface IF_PSTN_00 switch
  no shutdown

port fxo 0 1
  shutdown

Using rclone to sync a staff member’s OneDrive via admin link

Create the admin link in ‘365 admin

Start rclone.

Choose to create a new remote

choose onedrive (type 31 35 at the time of writing)

We don’t have a client id or client secret yet so leave blank as per the defaults

at the end you can say No, to editing the advanced config. After that you should be offered the option to sign in via a browser. Do that and use your admin account.

Back in the command prompt, continuing the rclone setup..
For the config_type, choose number 6 (“Type in SiteID“)

Open up the admin link from earlier in your browser, and grab the site ID from the Sync button in the Onedrive web-folder view.

You can either see this in dev-tools in the network request history (chrome F12), or you can Copy library ID from the middle of the screen and extract it from the url there (that is easiest). It’s url-encoded but that’s fine. Just take everything after &siteId= up to the next &, so for example here is an extract from one I just did. We would want %7bea……..%7D:
&siteId=%7Bea459e9b%2D37fd%2D44b5%2Da5f3%2D4434244cd813b%7D&webId=%7B86f7034

Type that in for your site ID in rclone.

Then rclone will find the OneDrive business drive and let you choose it (number 1 in the list below)

All good. Now you can sync it to your file server or whatever.

I use a scheduled task running rclone as below:

c:\rclone\rclone.exe -v --stats 30s copy james-onedrive: D:\OneDriveBackup\James --log-file=C:\Sharepoint-backup-log.txt

Virtual Worlds Installer “Restart Required”

Despite restarting the computer, this app would not install, instead stating “Restart Required, a computer restart is required”

Slightly frustrating that the supplier of the software was not able to resolve the problem and it was left to me to try to figure it out for our customer.

The supplier / developer ought to know exactly what it is checking when it says Restart Required. I could see that their support team had checked the usual PendingFileRenameOperations stuff. I checked anything else I was aware of too such as Windows Update RebootRequired.

In the end I used process monitor to capture all registry access, filtered by the installer application. There were of course 10s – 100s of thousands of rows to sift through, but I filtered for ‘update’ or ‘restart’ etc. and found the part of the trace where it was doing these checks, and one by one looked at them in the registry.

In this instance it was HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Services\Pending

I changed this to notPending, and lo-and-behold all good.

Honeywell PD45S ZSIM.FNT ZPL font alias

I’ve spent two days* and printed so many labels. Piles and piles of labels, and I continue doing the same remotely from home and checking the Image Buffer through my browser to see what the printer at the office is producing. All I wanted was a scalable non-bold font! SST Thai is inbuilt and would do nicely, but could I get the font aliasing to work? No way. Well, yes, now finally. What a relief.

Of course it doesn’t help that you have to restart the printer every time you alter or edit the alias file (or do you? see below), and there is no information or debugging for this sort of thing, all you can do is try a print and see if it works.

Anyway it turns out that despite the Honeywell documentation (what little I could find) stating that the ZSIM.FNT alias file should be placed in /home/user, this is incorrect. In fact the alias file should be placed in /home/user/fonts

I have more good news. Now that I have the thing working, I can confirm that a restart is not required between changes. I was tinkering with the ZSIM.FNT alias file and I noticed that the change was picked up immediately.

The following ZSIM.FNT appears to do what I need:

Z#SST Thai#100#

That means: replace font Z with SST Thai, with magnification factor of 100%

Wonderful. I am so happy to have finally worked it out. This is now genuinely the highlight of my week.

*OK I was doing other stuff too, like trying to get a tiny FSC logo to be readable at 300dpi.

Server 2012 to 2012 R2 in place upgrade stuck on black screen during reboot

This is on a Poweredge T110 II

Trying to upgrade a 2012 (non-R2) DC to 2022.
That jump isn’t possible, so I am upgrading to 2012 R2 first.

After in-Windows initial phase (which took ages), upon reboot there was the windows logo and twirls for a moment, then screen off (DPMS), then screen back on, but no mouse cursor and nothing happening, no display.
No disk activity.
Keyboard responding – num lock , caps lock, but can’t do anything.
waited ages.
powered off and back on, forced VGA / low-res driver, no difference.


System was already using Microsoft Basic display driver anyway, and no other unusual drivers present as far as I can tell.

Gave up.
Solution:
Upgrade to 2016 first instead. Much much faster initial phase of upgrade too – doesn’t run though and try to reconcile every hotfix and update that has been installed. What took almost an hour on 2012 -> 2012 R2 is taking 10 minutes.

Server 2012 R2 Essentials in place upgrade to 2022

The option to keep settings and apps is not present if the current edition (as returned by DISM /online /get-currentedition) is ServerSolution (a.k.a Essentials)

use DISM to upgrade with the KMS key to 2012 R2 standard:

dism /online /set-edition:serverstandard /productkey:D2N9P-3P6X9-2R39C-7RTCD-MDVJX /accepteula

then do in place upgrade to 2022.

Remember 2022 essentials *is* 2022 standard now. It’s a STD product key.

You can’t use EVAL media to upgrade either.

Mikrotik CAPsMAN out-of-hours Wi-Fi disablement / time-conditions.

Script scheduled to run every minute.

:local time [/system clock get time];
:if ($time >= "19:00:00" || $time <= "06:30:00") do={
	:foreach i in=[/caps-man interface find where disabled=no] do={:log info "Disabling CAPsMAN interface $i due to out-of-hours time"; /caps-man interface disable $i}
} else={
	:foreach i in=[/caps-man interface find where disabled=yes] do={:log info "Enabling CAPsMAN interface $i due to workday-hours"; /caps-man interface enable $i}
}