LincStation N1 & TrueNAS Scale

10 views
Skip to first unread message

Roger M. Jenson

unread,
Mar 7, 2025, 7:59:52 AMMar 7
to Milwau...@googlegroups.com
Yesterday I installed TrueNAS Scale on the LincStation N1 that had
Unraid installed. I plan to use it for a demonstration at the March 2025
meeting.

Having Fun,
Roger M. Jenson


Roger M. Jenson

unread,
Mar 10, 2025, 1:17:33 PMMar 10
to Milwaukee Linux Users Group
At the March 2025 meeting I demonstrated what I had accomplished in the
previous two days installing and configuring TrueNAS Scale.

After installing the docker Nextcloud and ZeroTier I am in new territory
configuring docker apps in the TrueNAS Scale management interface. I
will start with ZeroTier first so I can securely access the LincStation
N1 from anywhere.

Roger M. Jenson

unread,
Mar 11, 2025, 8:45:34 AMMar 11
to Milwau...@googlegroups.com
Using the instructions in the following YouTube video I can now securely
access TrueNAS Scale on the LincStation N1 whereever I have Internet access.

How to remote access TrueNAS Scale with Zerotier VPN

https://www.youtube.com/watch?v=4WJjQp3DX40

Next step is to setup Nextcloud.

Having Fun,
Roger M. Jenson


Tom

unread,
Apr 2, 2025, 6:00:08 PMApr 2
to Milwau...@googlegroups.com
Hey all, I have a python script that returns times and dates like this:
 
Dawn: 2025-04-02 06:02:58.182622-05:00
 
I'd like to isolate the time part of that only -- it seems to include not only the date, but also the offset from UTC. Sure, I could do this by taking the string apart and counting characters, but there should be a way to handle this more portably. I wondered if there's an easy way to do that.
 
This is how I'm getting these strings: (And I think they are strings, not some sort of datevalue.)
 
# Timezone name in an IANA compatible form: returns "America/Chicago" or etc
tziana=tzlocal.get_localzone_name()
city = LocationInfo('Menomonee Falls', 'Wisconsin', 'US/North America', mylat, mylon)
s = sun(city.observer, date=datetime.date(mynow), tzinfo=tziana)
 
print("Dawn:\t",s["dawn"],sep='')
 
Thanks in advance
-Tom

Richard Benkstein

unread,
Apr 2, 2025, 9:17:46 PMApr 2
to milwau...@googlegroups.com
Tom,

I would try piping to ack - first extracting the second section (default separator is the space) resulting in "06:02:58.182622-05:00" - then pipe that result to ack again defining the separator as the . (period) and extracting the first section which should give "06:02:58"  or the -(dash) giving "06:02:58.182522"

If this doesn't work, it has been a long time since I have done these types of things.

Rick Benkstein

--
Homepage: http://www.milwaukeelug.org/home
This forum online: https://groups.google.com/forum/#!forum/MilwaukeeLUG
---
You received this message because you are subscribed to the Google Groups "Milwaukee Linux User's Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to MilwaukeeLUG...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/MilwaukeeLUG/5802.-1058125620.1743631205%40gmail.com.

James Meyer

unread,
Apr 2, 2025, 10:12:17 PMApr 2
to Milwau...@googlegroups.com
Well it's hard to come up with anything based on the info given. As you said it might be a string or might not be.
Can you  report back
print(s)
print(type(s))

--

James Meyer

unread,
Apr 2, 2025, 10:17:56 PMApr 2
to Milwau...@googlegroups.com
if the type is a list, then also print out the type of the list element that you are interested in.

Ryan Pisani

unread,
Apr 3, 2025, 6:04:15 AMApr 3
to Milwau...@googlegroups.com
Date time objects can be manipulated without parsing a part strings. 

You can have the date time object printed out in any format you choose. 

from datetime import datetime

# Create a datetime object for the current date and time
now = datetime.now()

# Print the full date and time
print("Full datetime:", now)

# Print only the hour, minute, and second
print("Time only:", now.strftime("%H:%M:%S"))

--

Ryan Pisani

unread,
Apr 3, 2025, 7:50:10 AMApr 3
to Milwau...@googlegroups.com
I should have added... For your particular time stamp it's an ISO format 

from datetime import datetime

timestamp = "2025-04-02 06:02:58.182622-05:00"
dt = datetime.fromisoformat(timestamp)
print(dt)

Tom

unread,
Apr 3, 2025, 11:23:38 AMApr 3
to Milwau...@googlegroups.com
Value of s:
{'dawn': datetime.datetime(2025, 4, 3, 6, 1, 10, 240865, tzinfo=backports.zoneinfo.ZoneInfo(key='America/Chicago')), 'sunrise': datetime.datetime(2025, 4, 3, 6, 30, 31, 489166, tzinfo=backports.zoneinfo.ZoneInfo(key='America/Chicago')), 'noon': datetime.datetime(2025, 4, 3, 12, 55, 45, tzinfo=backports.zoneinfo.ZoneInfo(key='America/Chicago')), 'sunset': datetime.datetime(2025, 4, 3, 19, 21, 20, 118979, tzinfo=backports.zoneinfo.ZoneInfo(key='America/Chicago')), 'dusk': datetime.datetime(2025, 4, 3, 19, 50, 46, 760113, tzinfo=backports.zoneinfo.ZoneInfo(key='America/Chicago'))}
 
Type of s:
<class 'dict'>
 
Type of s["sunset"]
<class 'datetime.datetime'>
 
Type of s["sunrise]
<class 'datetime.datetime'>
 
 
Aha! It's not a string, it's an actual datetime.datetime
Seems like manipulating that should be easier.
 

Tom

unread,
Apr 3, 2025, 11:28:53 AMApr 3
to Milwau...@googlegroups.com
Result:
File "/usr/local/bin/suntimes.py", line 177, in
dt = datetime.fromisoformat(s["dawn"])
TypeError: fromisoformat: argument must be str
 
 
At 06:49 AM 4/3/2025 -0500, Ryan Pisani wrote:
dt = datetime.fromisoformat(timestamp)
print(dt)
 

Tom

unread,
Apr 3, 2025, 11:32:29 AMApr 3
to Milwau...@googlegroups.com
This approach worked perfectly:
print(s["dawn"].strftime("%H:%M:%S"))
 
That's exactly what I was looking for. Thanks!

James Meyer

unread,
Apr 3, 2025, 11:37:12 AMApr 3
to Milwau...@googlegroups.com

Awesome. Now use what Ryan said and you should be all set


Tom

unread,
Apr 3, 2025, 12:34:41 PMApr 3
to Milwau...@googlegroups.com
My code style is ugly. But here's my Python program I wrote with your valuable assistance. Please don't laugh.
P.S. It won't run as pasted below because my mail client throws away the tabs.
 
One question I have yet to answer: Checking the answers against a web site, it seems like it's correcting for DST, but it's not supposed to. The docs say it won't. That's why I put the "is_dst" function in; I was expecting to have to compensate by an hour if DST is true. But DST comes back True (at the moment) and the times are correct.
 
I guess I'll have to revisit in the fall after DST.
 
#!/usr/bin/python
# Return times for dawn, sunrise, dusk, sunset, etc.
# Note: most python libs for getting your timezone get a tuple with local zone names, like "CST, CDT" which
# the astral.sun package can't handle. What you need is the IANA timezone name, like "US/Chicago" or "US/Central"
 
import sys, os, getopt
import pytz
from astral import LocationInfo
from astral.sun import sun
from datetime import date, datetime, timezone, timedelta
import time
import tzlocal
 
ver = "2.3"
 
# My house in Waukesha County (Original has many more decimals)
mylat = 43.1
mylon = -88.1
 
# These are the formats for dates/times with and without -v (verbose) option.
longfmt ="%Y-%m-%d %H:%M:%S.%f"
shortfmt="%H:%M:%S"
 
# ================================================================================
 
def usage():
    print(me,ver)
    print("Get and display times of local dawn, sunrise, noon, dusk, sunset.")
    print("Times are based on a fixed longitude and latitude, hardcoded.")
    print("Options:")
    print(" -h Help")
    print(" -v Verbose output / debugging")
    print(" -d Show time of local Dawn")
    print(" -s Sunrise")
    print(" -n Noon (or -N)")
    print(" -S Sunset")
    print(" -D Dusk")
    print(" -L Location information (or -l)")
    print(" -t Time & date information")
    print(" -T Time Zone information")
    print(" -y Daylight Saving Time Status")
    print()
    print("NOTE: If multiple options are given, the times are printed in the order the events occur:")
    print("Dawn, Sunrise, Noon, Sunset, Dusk")
    print()
# ================================================================================
def is_dst(dt=None, timezone='UTC'):
    """Is daylight savings in effect?"""
    if dt is None:
        dt = datetime.datetime.utcnow()
        timezone = pytz.timezone(timezone)
        timezone_aware_date = timezone.localize(dt, is_dst=None)
        return timezone_aware_date.tzinfo._dst.seconds != 0
# ================================================================================
# PrintSunTime from dictionary s using key
def prst(k):
    if oVerb == True:
        print(k,"\t",s[k].strftime(longfmt)[:-4],sep='')
    else:
        print(s[k].strftime(shortfmt))
# ================================================================================
me = os.path.basename(sys.argv[0])
# Get argument list from command line and strip off the first one (it's the program name)
argList = sys.argv[1:]
 
#print("Options:",len(sys.argv))
 
if len(sys.argv) < 2:
print("Must enter at least one option.")
print()
usage()
sys.exit(2)
 
# Set options allowed on command line
options = "HhVvDdLlNnSsTty"
 
# ================================================================================
# Parse all the command line options
oDawn=False
oVerb=False
oDebg=False
oRise=False
oNoon=False
oSet=False
oDusk=False
oLoc=False
oTime=False
oZone=False
oDST=False
 
try:
    opts, leftovers = getopt.getopt(argList,options)
 
except getopt.GetoptError as err:
    print(str(err))
    print()
    usage()
    sys.exit(3)
 
for opt,arg in opts:
    if oDebg == True:
        print("opt =",opt,"\t","arg =",arg)
    if opt in ("-h","-H"):
        usage()
        sys.exit(0)
    if opt in ("-d"):
        oDawn = True
    if opt in ("-s"):
        oRise = True
    if opt in ("-n","-N"):
        oNoon = True
    if opt in ("-S"):
        oSet = True
    if opt in ("-D"):
        oDusk = True
    if opt in ("-l","-L"):
        oLoc = True
    if opt in ("-t"):
        oTime = True
    if opt in ("-T"):
        oZone = True
    if opt in ("-v"):
        oVerb=True
    if opt in ("-V"):
        oDebg=True
    if opt in ("-y"):
        oDST=True
# ================================================================================
if oDebg == True:
    print("oDawn\toVerb\toDebg\toRise\toNoon\toSet\toDusk\toLoc\toTime\toZone\toDST")
    print(oDawn,oVerb,oDebg,oRise,oNoon,oSet,oDusk,oLoc,oTime,oZone,oDST,sep="\t")
    print()
    print("opts:",opts,"\t","Leftovers:",leftovers)
# ================================================================================
mynow = datetime.today()
myyear = mynow.year
mymon = mynow.month
mydate = mynow.day
 
myhour = mynow.hour
mymin = mynow.minute
mysec = mynow.second
 
# This value is not useful
mytz = time.tzname
 
# This value is the IANA timezone name we need.
tziana=tzlocal.get_localzone_name()
 
# Determine if we're in daylight saving time now:
isdst = is_dst(mynow, timezone=tziana)
 
if oTime == True:
    print(f"{myyear}-{mymon:02d}-{mydate:02d}\t{myhour:02d}:{mymin:02d}:{mysec:02d}")
if oZone == True:
    print("timezone:",mytz,"\t", "IANA Timezone:",tziana,"\t","Is DST now:",isdst)
if oDST == True:
    print("DST: ",isdst)
 
# ================================================================================
city = LocationInfo('Menomonee Falls', 'Wisconsin', 'US/North America', mylat, mylon)
if oLoc == True:
    print("Name: ",city.name,"\t","Region: ",city.region,"\t","Latt: ",city.latitude,"\t","Long: ",city.longitude,sep='')
 
# print((
# f'Location: {city.name}/{city.region}\n'
# f'Timezone: {city.timezone}\n'
# f'Latitude: {city.latitude:.02f}; Longitude: {city.longitude:.02f}\n'
# ))
 
# ================================================================================
s = sun(city.observer, date=datetime.date(mynow), tzinfo=tziana)
 
# oDawn,oVerb,oDebg,oRise,oNoon,oSet,oDusk,oLoc,oTime,oZone,oDST
if oDawn == True:
    # key="dawn"
    # print(key,"\t",s[key],sep='')
    # print(s[key].strftime("%H:%M:%S"))
    prst("dawn")
if oRise == True:
    #print("Rise:\t",s["sunrise"],sep='')
    prst("sunrise")
if oNoon == True:
    prst("noon")
if oSet == True:
    prst("sunset")
if oDusk == True:
    prst("dusk")
 
# ================================================================================

Ryan Pisani

unread,
Apr 3, 2025, 12:40:42 PMApr 3
to Milwau...@googlegroups.com

Date time and time zone data is DST aware.  What are you trying to accomplish by checking for DST?  Local for time zone should already understand time offsets from UTC.


Tom

unread,
Apr 3, 2025, 1:53:13 PMApr 3
to Milwau...@googlegroups.com
The astra library "sun" package says it's not DST aware, but I'm getting the right answers, so maybe it is.

Ryan Pisani

unread,
Apr 4, 2025, 9:54:00 PMApr 4
to Milwau...@googlegroups.com
Date time objects can be manipulated without parsing a part strings. 

You can have the date time object printed out in any format you choose. 

from datetime import datetime

# Create a datetime object for the current date and time
now = datetime.now()

# Print the full date and time
print("Full datetime:", now)

# Print only the hour, minute, and second
print("Time only:", now.strftime("%H:%M:%S"))


Richard Benkstein

unread,
Apr 4, 2025, 9:54:10 PMApr 4
to MilwaukeeLUG
Tom,

Sorry - the command is awk.

Rick

Richard Benkstein

unread,
Apr 4, 2025, 9:54:19 PMApr 4
to MilwaukeeLUG
Tom,

Sorry for the third post

You can use awk or gawk - the pipe after your text would be |awk {'print $2'} |awk -F. {'print $1'}
(or the last -F. could be -F-)

Rick
Reply all
Reply to author
Forward
0 new messages