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.
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()
Through trial and error, I realised that both the cert and private key filenames that you upload, must end in .crt 🤷 Normally the key would be .key or at a push maybe .key.txt
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
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.
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.
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.
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.
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:
: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}
}
You must be logged in to post a comment.