feat: Ports all existing articles and images.
This commit is contained in:
101
content/articles/2023-08-10-coil-bypass-overview.md
Normal file
101
content/articles/2023-08-10-coil-bypass-overview.md
Normal file
@@ -0,0 +1,101 @@
|
||||
---
|
||||
tags: HVAC, design
|
||||
---
|
||||
|
||||
# Coil Bypass Overview
|
||||
|
||||
This is the first article in a series that explores the idea of a coil bypass strategy in an HVAC system. This article introduces you to a
|
||||
coil bypass strategy at a high level, future posts will dive deeper into the features, benefits, as well as the challenges of this style of
|
||||
system.
|
||||
|
||||
## What is a Coil Bypass
|
||||
|
||||
A coil bypass is not to be mistaken for a zoning system bypass, where airflow is "relieved" from the supply side of the system back into the
|
||||
return. Instead, a coil bypass diverts a portion of the airflow around the coil using a bypass damper(s). The bypass can serve several
|
||||
functions depending on the application, but in general it allows for a constant volume of air to be delivered to the space while the output
|
||||
of the coil can be shifted towards more or less dehumidification. In other words, it decouples the total system airflow from the coil
|
||||
airflow.
|
||||
|
||||
The bypassed air mixes with the supply air stream to act as a reheat source, however unlike a typical reheat source it does not add more
|
||||
sensible load to the structure, instead it just brings the supply air temperature closer to the existing home's temperature while still
|
||||
covering the latent and sensible loads of the home. A warmer duct system reduces the losses of the duct to unconditioned spaces as well as
|
||||
reduces the risk for duct condensation.
|
||||
|
||||
The coil bypass strategy, as far as I know, was pioneered by [Harry Boody](https://www.linkedin.com/in/harry-boody-9b8a4366/) of Energy
|
||||
Innovations and Scientific Environmental Design, Inc. However their websites are no longer active, so I'm not sure if they are still active
|
||||
in the HVAC design space or not.
|
||||
|
||||
## The Problem
|
||||
|
||||
| Why | |
|
||||
| -------- | ---------------------------------------------------------------- |
|
||||
| Question | Why would we want to utilize a strategy such as the coil bypass? |
|
||||
| Answer | Improved indoor air quality (IAQ) |
|
||||
|
||||
ASHRAE's recommandation for the amount of air changes per hour (ACH) in a residential structure to be in the range of 3-5 ACH, and in
|
||||
general the higher the better, along with a MERV 13+ filter. In some / most cases the system airflow does not meet that criteria, especially
|
||||
low load homes or high volume homes.
|
||||
|
||||
For example, let's imagine a single story ranch home that is 2,500 square feet with 9 foot ceilings. This home is relatively tight
|
||||
construction and after doing the heating and cooling loads we've selected a 2.5 Ton system for this home. It is located in a green grass
|
||||
climate that needs some priority on dehumidification and requires an airflow of 350 CFM/Ton (875 CFM).
|
||||
|
||||
We determine the volume of the conditioned space.
|
||||
|
||||
2,500 x 9 = 22,500 ft^3
|
||||
|
||||

|
||||
|
||||
| **Where:** | |
|
||||
| ---------- | ------------------------------------- |
|
||||
| **V** | _is the volume of the home_ |
|
||||
| **ACH** | _is the desired air changes per hour_ |
|
||||
| **60** | _conversion from hours to minutes_ |
|
||||
|
||||
Below is a table of the required CFM to meet the different air changes per hour.
|
||||
|
||||
| | CFM |
|
||||
| --------------- | :-----------------: |
|
||||
| (22,500 x 3)/60 | **_1,125 @ 3 ACH_** |
|
||||
| (22,500 x 4)/60 | **_1,500 @ 4 ACH_** |
|
||||
| (22,500 x 5)/60 | **_1,875 @ 5 ACH_** |
|
||||
|
||||
As you can see we have a discrepency of meeting even the low end of 3 ACH. The high end of 5 ACH is over 2x the airflow for our 2.5 Ton
|
||||
system. The coil bypass strategy is one viable way, by decoupling the total system airflow from the coil airflow without, which eliminates
|
||||
the need of an auxilary fan / system that circulates air through some sort of filtration system.
|
||||
|
||||
### Multi-Stage Systems
|
||||
|
||||
A challenge with multi-stage systems, even when sized properly, is that we often run at part-load conditions, and spend the majority of the
|
||||
time in lower stages. The lower stages often do worse at dehumidification than when running at full load.
|
||||
|
||||
When the equipment runs in lower stages on a traditional system the total system airflow is reduced even further from the recommended air
|
||||
changes per hour. This reduced airflow also causes the throw of the air from the registers to be reduced which can lead to increased odds of
|
||||
stratification, poor air mixing, and increased potential for poor mean radiant temperatures (MRT) of the surfaces. The decreased airflow in
|
||||
low stages, lowers the velocity in the duct system, while low velocity is not a concern, it does increase the duct gains and increase the
|
||||
possibility of condensation on the ducts when they're located outside of the thermal envelope of the building.
|
||||
|
||||
Let's imagine we have a duct system that has high wall registers located in a soffit at the interior wall that moves 100 CFM and we are
|
||||
trying to throw the air to the exterior wall which includes a window. The wall is @ 12 feet from the register. We've selected a register
|
||||
that meets the criteria, at high stage airflow it has a throw of 11.5 feet (shown as the green rectangle). When the system runs in low
|
||||
stage, the airflow is reduced to 70% of high stage (70 CFM), which would give us a throw from the register of @ 7 feet (shown as the red
|
||||
rectangle).
|
||||
|
||||

|
||||
|
||||
The reduced flow through the register causes the air to only make it about 60% across the room before reaching it's terminal velocity, which
|
||||
can cause the room to feel uncomfortable since the air never reaches the exterior wall and window.
|
||||
|
||||
By decoupling the fan from the coil airflow it is possible to run in low stages, still have adequate dehumidification performance out of the
|
||||
system, and achieve the proper throw from the registers.
|
||||
|
||||
## Conclusion
|
||||
|
||||
In this article we've begun to scratch the surface of what a coil bypass strategy is in an HVAC system, as well as some of the challenges
|
||||
that it can help solve. We've learned about why we may desire to decouple the total system airflow from the coil airflow.
|
||||
|
||||
In future articles we will continue to explore some of the features, benefits, and challenges presented by such a strategy.
|
||||
|
||||
## Related Resources
|
||||
|
||||
[HVAC School - Bypass Dehumidification / Airflow HVAC Design](https://hvacrschool.com/bypass-dehumidification-airflow-hvac-design/)
|
||||
38
content/articles/2023-08-10-rss-feed.md
Normal file
38
content/articles/2023-08-10-rss-feed.md
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
tags: software, how-to
|
||||
image: 2023-08-10-rss-feed.gif
|
||||
---
|
||||
|
||||
# Rss Feed
|
||||
|
||||
In this article I will show how to add this site's rss feed. In particular, we will be using [NetNewsWire](https://netnewswire.com) as the
|
||||
rss reader.
|
||||
|
||||
## What is an RSS Feed
|
||||
|
||||
An RSS feed will show you new posts, generally from a blog, without having to remember to check the website at regular intervals or signup
|
||||
for an email list for notifications.
|
||||
|
||||
NetNewsWire puts an RSS feed as:
|
||||
|
||||
**It's like podcasts** - but for _reading._
|
||||
|
||||
You consume an RSS feed, using an RSS reader application or extension in your browser.
|
||||
|
||||
## Step One
|
||||
|
||||
First find and download an RSS reader, you can download [NetNewsWire](https://netnewswire.com) for macOS from the link, or for iOS from the
|
||||
[AppStore](https://apps.apple.com/us/app/netnewswire-rss-reader/id1480640210).
|
||||
|
||||
## Step Two
|
||||
|
||||
Add the rss feed to stay up to date when I publish new articles.
|
||||
|
||||
1. Click the plus in the right side of the sidebar and select `New Feed...`
|
||||
1. In the URL field add: `https://mhoush.com/articles/feed.xml`
|
||||
1. Optionally give it a name
|
||||
1. Click the `Add` button.
|
||||
|
||||

|
||||
|
||||
That's it.
|
||||
68
content/articles/2023-09-08-pounds-of-water-removed.md
Normal file
68
content/articles/2023-09-08-pounds-of-water-removed.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
tags: tech-tip, HVAC, formulas, psychrometrics, psychrometric-chart
|
||||
---
|
||||
|
||||
# Pounds of Water Removed
|
||||
|
||||
This is an article that shows how to calculate the pounds of water removed from an air stream, given the entering conditions (return air
|
||||
stream) and the outlet conditions (supply air stream).
|
||||
|
||||
This is useful in the field when you want to calculate the amount of moisture removed from an air-conditioner or a dehumidifier. This
|
||||
article assumes that you have knowledge of a psychrometric chart. If you do not have basic knowledge of the psychrometric chart, then here
|
||||
are a couple articles to familiarize yourself.
|
||||
|
||||
## Articles
|
||||
|
||||
- [Understand Dew-Point](https://hvacrschool.com/understand-dew-point-absolute-moisture-right-side-psych-chart/)
|
||||
- [Impact of Adding or Removing Water from Air](https://hvacrschool.com/the-impact-of-adding-or-removing-water-from-air/)
|
||||
|
||||
## Scenario
|
||||
|
||||
Let's imagine that we have an air-conditioner that has the following measurements taken:
|
||||
|
||||
- Return Air: 75° / 50% RH
|
||||
- Supply Air: 55° / 81% RH
|
||||
|
||||
We plot the two values on the psychrometric chart (black line represents the return air conditions and blue line represents the supply air
|
||||
conditions).
|
||||
|
||||

|
||||
|
||||
We start by finding the corresponding dry-bulb temperature at the bottom of the chart and draw a straight line up to where it intersects the
|
||||
relative humidity curve. After that we draw a straight line to the right side of the psychrometric chart to find the grains of moisture per
|
||||
pound of air.
|
||||
|
||||
This gives us the following values:
|
||||
|
||||
- Return Air: 66 gr/lb
|
||||
- Supply Air: 52 gr/lb
|
||||
|
||||
We can then use the following formula to calculate the pounds of water removed.
|
||||
|
||||

|
||||
|
||||
| **Where** | |
|
||||
| ------------ | -------------------------------------------------------- |
|
||||
| **W** | _Weight of water in pounds per hour_ |
|
||||
| **4.5** | _Constant based on density / specific heat of moist air_ |
|
||||
| **CFM** | _Airflow in cubic feet per minute_ |
|
||||
| **∆G** | _Difference in grains of moisture_ |
|
||||
| **7000** | _Constant based on grains of moisture in saturated air_ |
|
||||
|
||||
## Solution
|
||||
|
||||
First, we solve for the difference in grains between the two air streams.
|
||||
|
||||
∆G = 66 - 52 = 14
|
||||
|
||||
Next, we've measured our airflow and have determined to have **797 CFM** of airflow across the evaporator coil, so we can substitute our
|
||||
values into the formula.
|
||||
|
||||

|
||||
|
||||
So, we are removing about 7 pounds of water per hour at these conditions.
|
||||
|
||||
Another thing to note is that 1 pound of water is approximately 1 pint of water, which can be useful when working with dehumidifiers that
|
||||
can often be rated in pints per day.
|
||||
|
||||
I hope you've found this article helpful, thanks for reading!
|
||||
66
content/articles/2023-09-14-why-mini-splits-stink.md
Normal file
66
content/articles/2023-09-14-why-mini-splits-stink.md
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
tags: HVAC
|
||||
---
|
||||
|
||||
# Why Mini Splits Stink
|
||||
|
||||
In this general article, I explain why I don't generally like to use mini-splits.
|
||||
|
||||
## The Positive Sides
|
||||
|
||||
When people say mini-splits, in general we mean "ductless" style units. These can either be high wall, floor mounted, or ceiling mounted
|
||||
consoles. These units do offer really high efficiency and becuase they're "ductless" you don't have duct gains/losses.
|
||||
|
||||
These units are common in many other countries and have been around for a long time. They do are generally quick and fairly easy to install,
|
||||
but are mostly a pain in the tail to work on.
|
||||
|
||||
So, the plus side to these units are that they are really efficient, they generally have models that have a high-heat output for colder
|
||||
climates, although this option is becoming more prevelant in traditional unitary style heat pumps as well. You do not have heat gains or
|
||||
losses due to ductwork being in unconditioned spaces.
|
||||
|
||||
## The Down Sides
|
||||
|
||||
Most mini-split systems do not do the greatest at humidity removal. This is partially because they use proprietary algorithms to control the
|
||||
blower and compressor. They do achieve long run-times, which is often good for comfort stand points, however there is generally not a good
|
||||
way to control / hack them to work towards achieving good IAQ.
|
||||
|
||||
These units offer next to no filtration, so in order to have filtration you need to utilize a stand-alone / portable filtration means. Which
|
||||
a lot of the portable filtration systems have problems of their own (come bundled with UV / PCO technology or other "space" technology that
|
||||
can lead to their own IAQ problems). It also introduces another fan, which may / may not be that efficient. In other words, when considering
|
||||
other items to make them more comparable to what a traditional system offers, are they really that much more efficient?
|
||||
|
||||
These systems also do not have a good method of offering basic fresh air control / management, so other systems, such as an ERV need to be
|
||||
installed to handle the fresh air requirements of the building.
|
||||
|
||||
The controls for these systems are often hard to understand / use. They do allow you to change fan speeds, but they control the compressor.
|
||||
The fans often run all the time, which is not necessarily a bad thing, but they don't really offer many ramping profiles or adjustments to
|
||||
change the blower speed when the compressor is off vs. on.
|
||||
|
||||
These systems get dirty quickly, are generally a pain to clean properly, and are not easily repairable. Manufacturer support is often poor,
|
||||
the documents aren't always translated very well, and most technicians hate to work on them.
|
||||
|
||||
# What about ducted models?
|
||||
|
||||
But what about the ducted models? Well, the ducted models are a step in the right direction. You can use filters on them, although some of
|
||||
the manufacturer's do not recommend installing better / improved filter cabinets (like a 4-5" media filter), however we have done that
|
||||
successfully many times and always include media filters as an option on our installations, but you do need to make sure that they have a
|
||||
very low pressure drop, as they a lot are not designed for very much static pressure.
|
||||
|
||||
The ducted models still generally have the same control problems, previously mentioned. If you read my introduction to the
|
||||
[coil-bypass-system](https://mhoush.com/posts/coil-bypass-overview/), you have a basic understanding that even most traditional systems /
|
||||
designers do not focus on the proper air-changes in a structure to maintain proper IAQ levels.
|
||||
|
||||
You can't easily pair mini-splits with larger fan-coils because they are "communicating" style systems.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Don't get me wrong, there are applications that are well suited for mini-splits. These are often applications like sun-rooms, garages, small
|
||||
server-rooms / network storage rooms, and many others. But in my opinion these are not at all my favorite and are generally really far down
|
||||
my list of options that I want to recommend to my clients.
|
||||
|
||||
As an industry, I feel we need to step back and refocus on the pillars of IAQ. Filtration, fresh-air, and humidity control. The
|
||||
manufacturers / government should put less emphasis on chasing efficiency just to shoot ourselves in the foot and loose the qualities that
|
||||
make traditional / unitary style systems cover more if not all of the 3 pillars of proper IAQ.
|
||||
|
||||
There's plenty that I did not cover and I'm sure I missed some things, but just needed to rant for a few minutes... Thank you for making it
|
||||
to the end!
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
tags: tech-tip, HVAC, formulas, design
|
||||
---
|
||||
|
||||
# Dehumidifier Sizing by Latent Load
|
||||
|
||||
This is a quick article to show how to calculate the size of dehumidifier needed based on the latent load of a building. This is useful if
|
||||
you've done a load calculation and know the latent load of the structure.
|
||||
|
||||
## Formulas
|
||||
|
||||
The formula above is used to solve for the pints per hour required to size a dehumidifier.
|
||||
|
||||
| Where | |
|
||||
| ----- | ------------ |
|
||||
| Ql | Latent load |
|
||||
| Ph | Pints / hour |
|
||||
|
||||
We can then convert to pints per day by multiplying the answer by 24 hours, below is the combined formula.
|
||||
|
||||

|
||||
|
||||
| Where | |
|
||||
| ----- | ----------- |
|
||||
| Ql | Latent load |
|
||||
| Pd | Pints / day |
|
||||
|
||||
In some cases you may want to size the dehumidifier for less than the full latent load, assuming that the air-conditioner (when sized
|
||||
properly) is going to cover the full latent load when at peak design temperatures and that the peak latent period for your area is during
|
||||
peak cooling demand.
|
||||
|
||||
## Example
|
||||
|
||||
Let's imagine we have done a load calculation and have a latent load of 4,334 BTU/h. So, plugging that into our above formula.
|
||||
|
||||

|
||||
|
||||
Or if we just want to cover the latent capacity at 85% of the full latent load.
|
||||
|
||||

|
||||
|
||||
This gives us some guidance that we would need to select a dehumidifier that is rated for 84-99 pints per day, depending on which condition
|
||||
we wanted to use.
|
||||
|
||||
I don't feel oversizing a dehumidifier, within reason, is that problematic (or at least it does not come with the same problems as an
|
||||
oversized air conditioner), so I would personally go for a 100-120 pint per day model dehumidifier in this application.
|
||||
|
||||
Thanks for reading!
|
||||
102
content/articles/2023-09-18-introducing-psychrometrics-cli.md
Normal file
102
content/articles/2023-09-18-introducing-psychrometrics-cli.md
Normal file
@@ -0,0 +1,102 @@
|
||||
---
|
||||
tags: HVAC, psychrometrics, software
|
||||
title: "Introducing Psychrometrics Cli"
|
||||
---
|
||||
|
||||
# Introducing Psychrometrics CLI
|
||||
|
||||
Today, I'm releasing a command line application that is built on top of my
|
||||
[swift-psychrometrics](https://github.com/swift-psychrometrics/swift-psychrometrics) package, that I open sourced over 2 years ago.
|
||||
|
||||
The application consists of many calculations / conversions for psychrometric properties of an air stream. The tool works for both imperial
|
||||
and metric units. The application will work natively on macOS, but can also be ran through a `docker` container on other platforms.
|
||||
|
||||
## Why
|
||||
|
||||
I spend a lot of time in my terminal, because I can work so much more efficiently. I discovered many years ago that the more I can do using
|
||||
simple applications and keyboard over a mouse and a web browser or native application the more I can accomplish. I understand this is
|
||||
intimidating for many who think they are _"not good with computers"._ I can assure that was me several years ago, I would only encourage you
|
||||
to not be afraid and give it a shot. We are at a time in society where it is easier than ever to get informed and learned new skills.
|
||||
|
||||
## Installation
|
||||
|
||||
For complete installation instructions, you can view the [github](https://github.com/swift-psychrometrics/psychrometrics-cli) repository.
|
||||
|
||||
The following instructions are based on using macOS.
|
||||
|
||||
### Open your terminal application.
|
||||
|
||||
Personally, I use [iTerm2](https://iterm2.com/), however you can use the default `Terminal` app. Found at
|
||||
`/Applications/Utilities/Terminal.app`.
|
||||
|
||||
## Install Homebrew
|
||||
|
||||
We use [Homebrew](https://brew.sh) for package distribution of the pre-built application binaries. You can follow their instructions to
|
||||
install.
|
||||
|
||||
### Tap our custom formula tap.
|
||||
|
||||
```bash
|
||||
brew tap swift-psychrometrics/formula
|
||||
```
|
||||
|
||||
### Install the psychrometrics application
|
||||
|
||||
```bash
|
||||
brew install psychrometrics
|
||||
```
|
||||
|
||||
That's it!
|
||||
|
||||
## Usage
|
||||
|
||||
I will run through a couple of the commands that are supplied with the application and show what you can expect the outputs to be.
|
||||
|
||||
### Properties
|
||||
|
||||
The following command will output a bunch of the psychrometric properties of an air stream. There are several ways to call it, but generally
|
||||
you will supply the dry bulb temperature and the relative humidity.
|
||||
|
||||
Below, we calculate the psychrometric properties based on 75°F and 50% humidity.
|
||||
|
||||
```bash
|
||||
psychrometrics --dry-bulb 75 --relative-humidity 50
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Dehumidifier Sizing
|
||||
|
||||
If you've read some of my recent articles on calculating the
|
||||
[dehumidifier size required based on the latent load](https://mhoush.com/posts/sizing-dehumidifier-by-latent-load/), the application also
|
||||
ships with a calculation that will do this for you and has the ability to calculate it at different `coverages` that you can supply.
|
||||
|
||||
For example if we've done a load calculation and determined that we have a latent load of `4,334 BTU/h` then we could run the following
|
||||
command to see what size dehumidifier is needed for `100%, 85%, and 70%` of the latent load.
|
||||
|
||||
```bash
|
||||
psychrometrics dh size --coverage 100 85 70 --verbose 4334
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Pounds of Water Removed
|
||||
|
||||
I also recently wrote an article about [calculating the pounds of water removed](https://mhoush.com/posts/pounds-of-water-removed/) from an
|
||||
air stream given the grains of moisture removed.
|
||||
|
||||
Below is an example of calculating the pounds of water removed per hour based on the example in the article (14 delta-grains)
|
||||
|
||||
```bash
|
||||
psychrometrics dh pounds-removed --delta 14 --cfm 797 --verbose
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Help
|
||||
|
||||
You can use `--help` option to show help and the list of commands provided.
|
||||
|
||||

|
||||
|
||||
If you have any questions then feel free to email or message me. I hope some of you may find this application useful.
|
||||
@@ -0,0 +1,241 @@
|
||||
---
|
||||
tags: HVAC, programming, software
|
||||
---
|
||||
|
||||
# Introduction to Programming for HVAC Part-1
|
||||
|
||||
This is part one of a series of articles to help HVAC technicians (or others) get started in developing their skills to program. This can
|
||||
help to automate everyday tasks or just familiarize themselves with some of the tools used by programmers.
|
||||
|
||||
## Why
|
||||
|
||||
I think if nothing else, this series can help gain knowledge, tips, and tricks to make you more comfortable with your computer. I hope that
|
||||
you will at least learn how to use your `terminal` application and more specifically `vim` motions and keybindings (more on that in another
|
||||
article).
|
||||
|
||||
The goal of this article is to just get a machine setup with tools and to start exploring. I am a shill for `macOS`, so all of these will be
|
||||
specifically geared towards that and my workflows, most everything that is showcased should also work on `linux` machines (not sure about
|
||||
`windows`), although you may have to search for specific instructions on installing software for other platforms.
|
||||
|
||||
What I have learned on my journey in programming is that the more you can lean on small software packages that focus on a single task, but
|
||||
do them well, the better. The less you use your mouse, the more productive you can be. The more you can work with `text` files and formats
|
||||
the more portable and transformable your workflows can be.
|
||||
|
||||
## Getting Started
|
||||
|
||||
The first thing that we will focus on is becoming familiar with the terminal application. On macOS the terminal application is located at
|
||||
`/Applications/Utilities/Terminal.app`. However, rather than click around to find it, you can use the `⌘<space>` to pull up your spotlight
|
||||
search, then type `Terminal` to select the terminal application.
|
||||
|
||||

|
||||
|
||||
### Terminal Overview
|
||||
|
||||
Your terminal is a program that allows you to run programs by typing commands into it's window. There are a lot of built-in commands and a
|
||||
bunch that you can install. The terminal is very customizable (and once familiar, you will constantly be tweaking / adjusting to suit your
|
||||
needs). Right now customization is not what we will focus on, however in future articles I will provide tips and tricks on customizing it.
|
||||
Right now, we only need to know how to open it up and type in commands.
|
||||
|
||||

|
||||
|
||||
Below is an image / explanation of what the default status line includes.
|
||||
|
||||

|
||||
|
||||
### Learn Basic Commands (Built-in)
|
||||
|
||||
Here are a few basic commands that you should familiarize yourself with, as you will use them often when working inside of a terminal.
|
||||
|
||||
### Change Directory
|
||||
|
||||
`cd` (change directory) is the command that allows you to move around your file system when inside the terminal.
|
||||
|
||||
> **Note:** `~` is a representation of your `Home` directory.
|
||||
|
||||
```bash
|
||||
cd ~/Documents
|
||||
```
|
||||
|
||||
The above command will move you into your Documents directory.
|
||||
|
||||
> **Note:** If there are spaces in the name of the directory you try to move to then the easiest way is to wrap the name in quotes.
|
||||
|
||||
```bash
|
||||
cd "~/Documents/Product Concepts"
|
||||
```
|
||||
|
||||
Some other things to understand when moving around / supplying arguments to the `cd` command.
|
||||
|
||||
You can use `..` to go backwards / move up to the parent directory. For example, say we are in the `~/Documents` directory, to go back up to
|
||||
the home directory we could use the following:
|
||||
|
||||
```bash
|
||||
cd ..
|
||||
```
|
||||
|
||||
These can be chained together as well. For example say we are located in the `~/Documents/Product Concepts` directory, we could use the
|
||||
following to go up two directory levels back to the home directory.
|
||||
|
||||
```bash
|
||||
cd ../..
|
||||
```
|
||||
|
||||
> **Pro-Tip:** You can use the `<tab>` key when navigating to auto-complete, generally typing a few characters followed with the `<tab>` key
|
||||
> will auto-complete for you.
|
||||
|
||||
### List files
|
||||
|
||||
Use `ls` to output a list of files and directories where you are located.
|
||||
|
||||
```bash
|
||||
ls
|
||||
```
|
||||
|
||||
_Example Output when in my ~/Documents directory_
|
||||
|
||||
```bash
|
||||
Estimates.app
|
||||
InkscapeDrawings
|
||||
KwikModel
|
||||
MyAparment
|
||||
NCISummit
|
||||
Personal
|
||||
Product Concepts
|
||||
Receipts.receipts
|
||||
RingCentral
|
||||
SketchUP
|
||||
Tech-Tips
|
||||
desktop.ini
|
||||
espanso-migrate-backup
|
||||
espanso-migrate-backup-2
|
||||
```
|
||||
|
||||
Using options with `ls` to show more statistics and hidden files. There are often hidden files on your computer that are used for
|
||||
application support or other purposes, these files are not shown using the default command. Hidden files start with a `.`, below is an
|
||||
example of showing hidden files in your home directory.
|
||||
|
||||
```bash
|
||||
ls -la ~/
|
||||
```
|
||||
|
||||
> **Note:** Above I added the `~/` which will allow you to list the files in your home directory even if you currently are not there in your
|
||||
> terminal, if you were already there (for example by using `cd ~/` then you would not need to use that at the end of the command.
|
||||
|
||||
_Example Output_
|
||||
|
||||
```
|
||||
total 168
|
||||
drwxr-xr-x+ 46 michael staff 1472 Sep 22 10:45 .
|
||||
drwxr-xr-x 6 root admin 192 Sep 22 09:08 ..
|
||||
-r-------- 1 michael staff 7 Apr 8 2021 .CFUserTextEncoding
|
||||
-rw-r--r--@ 1 michael staff 14340 Sep 18 10:15 .DS_Store
|
||||
drwx------+ 5 michael staff 160 Sep 20 17:03 .Trash
|
||||
-rw-r--r-- 1 michael staff 186 Sep 12 15:20 .actrc
|
||||
drwxr-xr-x 4 michael staff 128 Dec 13 2021 .bin
|
||||
drwxr-xr-x 3 michael staff 96 Mar 6 2023 .bundle
|
||||
drwxr-xr-x 7 michael staff 224 Sep 12 11:40 .cabal
|
||||
drwxr-xr-x 7 michael staff 224 Sep 12 15:20 .cache
|
||||
drwxr-xr-x 13 michael staff 416 Aug 10 08:47 .config
|
||||
drwx------ 3 michael staff 96 Jun 21 2021 .cups
|
||||
drwxr-xr-x 12 michael staff 384 Sep 15 15:22 .docker
|
||||
drwxr-xr-x 20 michael staff 640 Sep 19 08:11 .dotfiles
|
||||
drwxr-xr-x 4 michael staff 128 Jul 26 2021 .gem
|
||||
drwxr-xr-x 3 michael staff 96 Oct 11 2021 .jssc
|
||||
-rw------- 1 michael staff 20 Sep 22 10:45 .lesshst
|
||||
drwxr-x--- 3 michael staff 96 Mar 29 08:47 .lldb
|
||||
drwxr-xr-x 8 michael staff 256 Mar 1 2023 .local
|
||||
drwxr-xr-x 4 root staff 128 Apr 12 2021 .newtek
|
||||
drwxr-xr-x 5 michael staff 160 Dec 13 2021 .npm
|
||||
-rw------- 1 michael staff 27436 Apr 10 10:21 .psql_history
|
||||
drwxr-xr-x 7 michael staff 224 Apr 18 2022 .ssh
|
||||
drwxr-xr-x 6 michael staff 192 Sep 21 09:06 .swiftpm
|
||||
lrwxr-xr-x 1 michael staff 25 Dec 27 2021 .tmux.conf -> .dotfiles/tmux/.tmux.conf
|
||||
drwxr-xr-x 8 michael staff 256 Mar 27 16:14 .twilio-cli
|
||||
drwxr-xr-x 6 michael staff 192 Sep 18 11:08 .vim
|
||||
-rw------- 1 michael staff 23086 Sep 21 09:45 .viminfo
|
||||
-rw-r--r-- 1 michael staff 254 Sep 21 09:32 .wget-hsts
|
||||
lrwxr-xr-x 1 michael staff 43 Jan 3 2022 .zshenv -> /Users/michael/.dotfiles/zsh/config/.zshenv
|
||||
drwxr-xr-x 8 michael staff 256 Dec 14 2021 AmazonWorkDocsCompanion
|
||||
drwx------@ 4 michael staff 128 Dec 13 2021 Applications
|
||||
lrwxr-xr-x 1 michael staff 40 Jun 6 12:00 Applications (Parallels) -> /Volumes/Bucket/Applications (Parallels)
|
||||
drwx------@ 30 michael staff 960 Sep 21 08:54 Desktop
|
||||
drwx------@ 19 michael staff 608 Sep 14 10:15 Documents
|
||||
drwx------@ 21 michael staff 672 Sep 21 09:43 Downloads
|
||||
drwx------+ 115 michael staff 3680 Sep 14 10:04 Library
|
||||
drwxr-xr-x 3 michael staff 96 Sep 8 13:06 LocalProjects
|
||||
lrwxr-xr-x 1 michael staff 29 Dec 30 2021 Movies -> /Volumes/Bucket/Videos/Movies
|
||||
lrwxr-xr-x 1 michael staff 21 Dec 30 2021 Music -> /Volumes/Bucket/Music
|
||||
drwx------@ 2 michael staff 64 Mar 6 2023 Parallels
|
||||
drwx------@ 7 michael staff 224 Sep 14 09:52 Pictures
|
||||
drwxr-x---+ 4 michael staff 128 Apr 8 2021 Public
|
||||
drwxr-xr-x+ 3 michael staff 96 Sep 14 09:52 Sites
|
||||
drwxr-xr-x 3 michael staff 96 Jun 7 2021 WorkDocs Drive
|
||||
drwxr-xr-x 3 michael staff 96 Sep 18 11:36 go
|
||||
```
|
||||
|
||||
As you can see, I have a lot of hidden files and folders, your output will probably look much different than mine.
|
||||
|
||||
### Clearing the Terminal
|
||||
|
||||
Often times you may want to clear the terminal screen. You can use the `clear` command to clear the screen of the terminal.
|
||||
|
||||
```bash
|
||||
clear
|
||||
```
|
||||
|
||||
Or use a keyboard shortcut `⌃l` (`<control>l`)
|
||||
|
||||
### Creating Directories
|
||||
|
||||
Use `mkdir` (make directory) to create a directory.
|
||||
|
||||
First, let's move into the `tmp` directory, the `tmp` directory is a directory on your file system that is typically used for applications
|
||||
to write temporary logs / files to, it get's erased everytime your computer is restarted. We can use the `cd` command that we learned
|
||||
earlier.
|
||||
|
||||
```bash
|
||||
cd /tmp
|
||||
```
|
||||
|
||||
Next, let's create a new directory called "MyDirectory".
|
||||
|
||||
```bash
|
||||
mkdir MyDirectory
|
||||
```
|
||||
|
||||
#### Gotcha's with 'mkdir'
|
||||
|
||||
By default you can't create directories that are multiple levels deep, unless the directories already existed or we provide the `-p` option.
|
||||
For example, if we want to create a directory at `/tmp/MyOtherDirectory/Nested/Deeply` then we could use the following command when inside
|
||||
the `tmp` directory.
|
||||
|
||||
```bash
|
||||
mkdir -p MyOtherDirectory/Nested/Deeply
|
||||
```
|
||||
|
||||
Now, try out using the `<tab>` key with the `cd` command to navigate to the `Deeply` folder.
|
||||
|
||||
```bash
|
||||
cd MyOther <tab> <tab> <tab>
|
||||
```
|
||||
|
||||
### Open Command
|
||||
|
||||
You can use the open command to open files or folders in the default application for the file type.
|
||||
|
||||
For example, if we want to open a `Finder` window while in the `/tmp` directory, we can use the following command:
|
||||
|
||||
```bash
|
||||
open .
|
||||
```
|
||||
|
||||
### Manual Pages
|
||||
|
||||
Lastly, to learn more about commands you can use the `man <command>`. To bring up the manual pages for the command in the terminal. You can
|
||||
use the arrow keys to navigate around the manual pages and type the letter `q` to quit / close the manual pages.
|
||||
|
||||
```bash
|
||||
man ls
|
||||
```
|
||||
|
||||
That is it for the first installment in this series. I hope you learned something and have better understanding of using your terminal.
|
||||
@@ -0,0 +1,109 @@
|
||||
---
|
||||
tags: HVAC, programming, software
|
||||
title: "Introduction to Programming for HVAC Part-2"
|
||||
---
|
||||
|
||||
# Introduction to Programming for HVAC Part-2
|
||||
|
||||
In this article, learn about installing a package manager. If you missed it, check out the
|
||||
[first](https://mhoush.com/posts/introduction-to-programming-for-hvac-1/) article in the series where we learned about using your terminal.
|
||||
This article builds upon that foundation.
|
||||
|
||||
## What is a Package Manager
|
||||
|
||||
A package manager is a piece of software that helps to install software and manage updates for your system. For me, the first thing that I
|
||||
do with a new machine is install `Homebrew`. [Homebrew](https://brew.sh) is my preferred package manager for `macOS`.
|
||||
|
||||
## Why
|
||||
|
||||
A package manager is nice because often software relies / requires other dependencies in order to work properly. By using a package manager
|
||||
it will make sure that the correct dependencies are installed for the software that you need to run. It allows you to be able to update and
|
||||
manage software through a centralized interface.
|
||||
|
||||
## Installation
|
||||
|
||||
Installation is simple. Open up your terminal and enter the following command (easiest to just copy / paste from the homepage linked above).
|
||||
|
||||
```bash
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
```
|
||||
|
||||
This will prompt you for your password in order to create some directories and install the required software for `brew` to work. The
|
||||
installation may take some time, while it downloads the command line tools for `Xcode`.
|
||||
|
||||
When completed, follow the `Next Steps` and copy / paste the command listed, that should look like below.
|
||||
|
||||
```bash
|
||||
(echo; echo 'eval "$(/opt/homebrew/bin/brew shellenv)"') >> /Users/<you>/.zprofile
|
||||
eval "$(/opt/homebrew/bin/brew shellenv)"
|
||||
```
|
||||
|
||||

|
||||
|
||||
The first line of this command sets up some things in your shell profile (which we have not discussed yet) that will make `Homebrew`
|
||||
available to you anytime you start a new session in your terminal. The second line of the command makes it available in your current
|
||||
terminal session.
|
||||
|
||||
Next run the following command and make sure that everything is setup correctly.
|
||||
|
||||
```bash
|
||||
brew doctor
|
||||
```
|
||||
|
||||
Which should output the following:
|
||||
|
||||
```
|
||||
Your system is ready to brew.
|
||||
```
|
||||
|
||||
### Terminology
|
||||
|
||||
Homebrew calls command line applications `formula` and normal graphical applications `casks`. It has the ability to install both styles of
|
||||
applications.
|
||||
|
||||
## Search Command
|
||||
|
||||
The following command is used to search for software packages:
|
||||
|
||||
```bash
|
||||
brew search chrome
|
||||
```
|
||||
|
||||
## Open a Homepage
|
||||
|
||||
The following command can be used to view the homepage of a formula or cask in your browser:
|
||||
|
||||
```bash
|
||||
brew home google-chrome
|
||||
```
|
||||
|
||||
## Update Homebrew
|
||||
|
||||
The following command is used to update homebrew:
|
||||
|
||||
```bash
|
||||
brew update
|
||||
```
|
||||
|
||||
## Update packages installed on your system
|
||||
|
||||
The following command is used to update software that is installed / managed by homebrew.
|
||||
|
||||
```bash
|
||||
brew upgrade
|
||||
```
|
||||
|
||||
You can combine the update and upgrade commands, which will update homebrew and upgrade all the software it manages on you machine with the
|
||||
following command.
|
||||
|
||||
```bash
|
||||
brew update && brew upgrade
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
That is it for this article. I will say that for me, when I find a piece of software that I want to use, I generally try to search for it in
|
||||
`brew` first, before installing it via other means.
|
||||
|
||||
I hope you've found this article helpful. In the next article we will start to use the skills that we've learned in these first two articles
|
||||
and write our first program / script.
|
||||
@@ -0,0 +1,125 @@
|
||||
---
|
||||
tags: HVAC, programming, software
|
||||
---
|
||||
|
||||
# Introduction to Programming for HVAC Part-3
|
||||
|
||||
In this article we will put together some of the pieces from the last 2 articles, and build our first program. If you have missed the first
|
||||
articles, then you can catch up [here](https://mhoush.com/series/programming-for-hvac/) before continuing with this article.
|
||||
|
||||
## Getting Started
|
||||
|
||||
We are going to make our first script / program. This first program is really just setting up some building blocks for our next program we
|
||||
will write, that will remove the background from an image.
|
||||
|
||||
### Creating a scripts directory
|
||||
|
||||
We learned in the [first article](https://mhoush.com/posts/introduction-to-programming-for-hvac-1/) how to use our terminal. Today we are
|
||||
going to use some of the commands we learned to create a directory where we can store our script and future scripts that we write.
|
||||
|
||||
**Create a directory**
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.local/bin
|
||||
```
|
||||
|
||||
The above command will create a "hidden" directory in your home folder. We can go ahead and move into the directory we just created.
|
||||
|
||||
> **Note:** The `-p` option allows us to create nested directories if the parent directory doesn't exist.
|
||||
|
||||
```bash
|
||||
cd ~/.local/bin
|
||||
```
|
||||
|
||||
### Hello World
|
||||
|
||||
It is common in programming to start out with a "Hello World" program when learning a new scripting paradigm. So let's jump in and get
|
||||
started.
|
||||
|
||||
**Creating our script file:**
|
||||
|
||||
```bash
|
||||
touch hello-world.sh
|
||||
```
|
||||
|
||||
**Now open the file:**
|
||||
|
||||
```bash
|
||||
open hello-world.sh
|
||||
```
|
||||
|
||||
The above command should open the file in the `TextEdit` application. In order to make the text edit application to not auto-capitalize
|
||||
words and play more nicely, we need to adjust some settings. Open the settings by pressing `⌘,`.
|
||||
|
||||
In the **Format** section, select _Plain text_ and in the **Options** section de-select _Check spelling as you type_.
|
||||
|
||||

|
||||
|
||||
At this point for changes to take place, you will need to close the file and re-open.
|
||||
|
||||
> **Tip:** In your terminal you can run the last command in your history by using the `↑` (Up) arrow key.
|
||||
|
||||
Now that the file is open again, we will write our hello-world program. The contents of your file should look like the following:
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
|
||||
echo 'Hello World!'
|
||||
```
|
||||
|
||||
The first line is referred to as the `shebang`, this tells your computer which shell interperter to run your file. I have not explained the
|
||||
shell yet, but it currently would just muddy the waters a bit, but there are several shell interperters on your computer with the `sh` posix
|
||||
shell being one of the most universal / lowest level ones, which is why I'm choosing this one (in other words this script would work on just
|
||||
about any machine you were on).
|
||||
|
||||
The second line we are using the built-in `echo` command and passing it the 'Hello World!' argument.
|
||||
|
||||
Now save and close the file `⌘s` (to save) `⌘q` (to quit the text edit application).
|
||||
|
||||
**Run the program from your terminal:**
|
||||
|
||||
```bash
|
||||
/bin/sh hello-world.sh
|
||||
```
|
||||
|
||||
You should see that `Hello World!` was printed to your console.
|
||||
|
||||

|
||||
|
||||
### Make Executable
|
||||
|
||||
Now that we have our basic script working, let's make it an executable.
|
||||
|
||||
**In your terminal, type the following:**
|
||||
|
||||
```bash
|
||||
chmod u+x hello-world.sh
|
||||
```
|
||||
|
||||
This will change the mode of the file type to be an executable.
|
||||
|
||||
Now move / rename the file so we don't have to call it using `.sh` extension:
|
||||
|
||||
```bash
|
||||
mv hello-world.sh hello-world
|
||||
```
|
||||
|
||||
Now that the file is executable, we can execute it by just calling the name of the file.
|
||||
|
||||
```bash
|
||||
./hello-world
|
||||
```
|
||||
|
||||
> **Note:** We have to prefix the file name with `./` in the above command so that it knows where to find our file. The `./` is saying run
|
||||
> this file in our current directory. In the future we will setup our shell so that it knows to look in our `~/.local/bin` directory for
|
||||
> scripts, so that we can call them without this prefix.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Congratulations, in this article we wrote our first program. We learned how to edit the file, set it's permissions, and execute the program
|
||||
from our terminal. I should mention that the `TextEdit` application is generally not how you would program, people typically use what is
|
||||
known as an `IDE (integrated development environment)`, however I chose to use the `TextEdit` application because it is built-in to `macOS`
|
||||
and allowed us to accomplish our goal without downloading other software.
|
||||
|
||||
In our upcoming articles, we will write a program that I hope is useful to you / something that you can build upon and use for a long time.
|
||||
Thank you for reading to this point.
|
||||
@@ -0,0 +1,205 @@
|
||||
---
|
||||
tags: HVAC, programming, software
|
||||
---
|
||||
|
||||
# Introduction to Programming for HVAC Part-4
|
||||
|
||||
This article builds upon our [last](https://mhoush.com/posts/introduction-to-programming-for-hvac-3/) article, so make sure to catch up
|
||||
before continuing with this article.
|
||||
|
||||
## Arguments
|
||||
|
||||
Before we start creating our program that will remove the background from images let's go over arguments in shell scripts. Arguments are
|
||||
supplied to shell scripts are separated by a space `" "`, as opposed to options which start with a `-<character>` or `--<word>`.
|
||||
|
||||
To illustrate this, let's change our `hello-world` script we wrote in the last article.
|
||||
|
||||
**Move into our scripts directory:**
|
||||
|
||||
```bash
|
||||
cd ~/.local/bin
|
||||
```
|
||||
|
||||
**Make a copy of the hello-world script:**
|
||||
|
||||
```bash
|
||||
cp hello-world greet
|
||||
```
|
||||
|
||||
Above we make a copy of the hello-world file and name the copy `greet`.
|
||||
|
||||
**Open the greet file:**
|
||||
|
||||
```bash
|
||||
open -a TextEdit greet
|
||||
```
|
||||
|
||||
> **Note:** Because the greet file is an executable, in order to open it in the `TextEdit` application we must supply the `-a` option.
|
||||
> Otherwise it will just run our `greet` program in another terminal. Use `man open` to read more about the open command.
|
||||
|
||||
**Edit the greet file:**
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
|
||||
echo "Hello, ${1}!"
|
||||
```
|
||||
|
||||
Make sure to save `⌘s` the file.
|
||||
|
||||
Take note that the quotes need to be changed to `"` (double quotes) from our original `hello-world` program.
|
||||
|
||||
The `${1}` is indicating that we will insert / interpret the first argument passed to our program and insert it at that location. Arguments
|
||||
are interpreted in order they are passed in with `${0}` always representing the filename of the program that is called (generally not needed
|
||||
/ used in your scripts).
|
||||
|
||||
**Test it out:**
|
||||
|
||||
```bash
|
||||
./greet Michael
|
||||
```
|
||||
|
||||

|
||||
|
||||
If you'd like to supply multiple words (or arguments that contain spaces) as a single argument then you can wrap them in quotes.
|
||||
|
||||
```bash
|
||||
./greet "Michael Housh"
|
||||
```
|
||||
|
||||
> **Tip:** Wrapping in quotes is especially useful for commands that take file paths, if any of the folders or file names contain spaces.
|
||||
|
||||
## More Useful Program
|
||||
|
||||
At this point, it's time to build a more useful program that we can use. First, we must download some dependencies for our program.
|
||||
|
||||
**Install imagemagick:**
|
||||
|
||||
```bash
|
||||
brew install imagemagick
|
||||
```
|
||||
|
||||
> **Note:** If you'd like to check out the documentation / website for imagemagick you can run `brew home imagemagick`.
|
||||
|
||||
This will take a bit for brew to install imagemagick and it's dependencies. When it's completed, we can check to make sure that imagemagick
|
||||
is installed by running the following command.
|
||||
|
||||
```bash
|
||||
magick --version
|
||||
```
|
||||
|
||||
It should output something along the lines of this below.
|
||||
|
||||
```bash
|
||||
Version: ImageMagick 7.1.1-17 Q16-HDRI aarch64 21569 https://imagemagick.org
|
||||
Copyright: (C) 1999 ImageMagick Studio LLC
|
||||
License: https://imagemagick.org/script/license.php
|
||||
Features: Cipher DPC HDRI Modules OpenMP(5.0)
|
||||
Delegates (built-in): bzlib fontconfig freetype gslib heic jng jp2 jpeg jxl lcms lqr ltdl lzma openexr png ps raw tiff webp xml zlib
|
||||
Compiler: gcc (4.2)
|
||||
```
|
||||
|
||||
> **Tip:** Don't forget, you can use the `clear` command to clear the terminal.
|
||||
|
||||
**Create our script:**
|
||||
|
||||
```bash
|
||||
touch mktrans
|
||||
```
|
||||
|
||||
We are going to name our script `mktrans` as a short for make transparent.
|
||||
|
||||
**Open the file:**
|
||||
|
||||
```bash
|
||||
open mktrans
|
||||
```
|
||||
|
||||
**The program:**
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# The input file path, passed in as the first argument.
|
||||
inputfile="${1}"
|
||||
|
||||
# The color to make transparent, optionally passed in as the second argument.
|
||||
# by default we handle / make white backgrounds transparent.
|
||||
color="${2:-white}"
|
||||
|
||||
# Use the built-in basename command to normalize the input file name
|
||||
# this will convert a file path, such as ~/Pictures/my-image.png to my-image.png.
|
||||
fullfilename=$(basename -- "$inputfile")
|
||||
|
||||
# Use the text of the `fullfilename` up to the first '.' as the file name.
|
||||
filename="${fullfilename%%.*}"
|
||||
|
||||
# Use the text after the last '.' as the file extension.
|
||||
extension="${fullfilename##*.}"
|
||||
|
||||
# Create the output file name to use.
|
||||
#
|
||||
# For an input file of `input.png`, our output name would be
|
||||
# `input-transparent.png`.
|
||||
#
|
||||
# This will output the file in the directory that we are
|
||||
# in when we use our script (which may different than where
|
||||
# the image is located)
|
||||
outputfile="${filename}-transparent.${extension}"
|
||||
|
||||
# Make the magick happen :)
|
||||
convert "${inputfile}" -fuzz 10% -transparent "${color}" "${outputfile}"
|
||||
|
||||
```
|
||||
|
||||
I've included comments in the program above, which is good practice, as there is high odds that you will forget what is going on when / if
|
||||
you open the file up in the future to look at it. We are using a lot of what is called parameter expansion magic in this file. You can read
|
||||
up more on what we are doing in the [bash documentation](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html).
|
||||
|
||||
This script is far from perfect, there are a lot of things to be improved upon. For example, if you download / save the banner image of this
|
||||
post and run this script, it will also remove some color in the wizards beard, eyes, and eye brows. However, it does work very well for my
|
||||
general use case, which is to remove the background from screenshots of pdf documents. It should be noted that it will not work on all types
|
||||
of images, some image types do not allow transparency, so it is safest to call this with input image being a `.png` image type, however you
|
||||
can use the `imagemagick` program that we downloaded to convert other image types to `.png`, but that will be left up to you to figure out.
|
||||
|
||||
## Using Our Program
|
||||
|
||||
This is going to assume that you have download the banner image at the top of this article. You can do this by right-clicking and choosing
|
||||
`Save As`. This should save the image in your downloads folder, and you can keep the name of `part4-banner.png`.
|
||||
|
||||
**Make the program executable:**
|
||||
|
||||
```bash
|
||||
chmod u+x mktrans
|
||||
```
|
||||
|
||||
**Make the image background transparent:**
|
||||
|
||||
```bash
|
||||
./mktrans ~/Downloads/part4-banner.png
|
||||
```
|
||||
|
||||
**Open the image:**
|
||||
|
||||
```bash
|
||||
open part4-banner-transparent.png
|
||||
```
|
||||
|
||||
It should look like below.
|
||||
|
||||

|
||||
|
||||
> **Note:** If you are viewing this site in _light_ mode, the image does not look that bad. Hit the moon button in the top above my profile
|
||||
> image to see some of the flaws of our program.
|
||||
|
||||
---
|
||||
|
||||
> **Tip:** Remove the image from the `~/.local/bin` by using `rm part4-banner-transparent.png`. Be aware that the `rm` command can not be
|
||||
> undone, so use with caution / knowledge. It is safer, until you are more comfortable to use the `Finder` application and move the file to
|
||||
> the trash. In `Finder`, you can show hidden directories by typing `⌘.` or go directly to the folder by typing `⇧⌘G` (shift + command + G)
|
||||
> and in the pop-up typing `~/.local/bin`.
|
||||
|
||||
---
|
||||
|
||||
That is it for this article. In the upcoming articles we will setup our `shell` environment so that we can use the commands we've built
|
||||
without having to navigate to the `~/.local/bin` directory. Thank you for reading to the end, I hope you're finding this series helpful.
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
tags: HVAC
|
||||
---
|
||||
|
||||
# Free quotes != good
|
||||
|
||||
I found myself re-reading the
|
||||
[ACCA Quality Installation Standard](https://www.acca.org/communities/community-home/librarydocuments/viewdocument?DocumentKey=b1d2a39d-fda8-4af9-b8de-0ae579bfe24a)
|
||||
recently and it got me thinking about the industries tendency of offering free quotes. In this article, I'd like to just focus in on the
|
||||
items that are required as what I'm calling "prior to installation" items.
|
||||
|
||||
## Prior to installation
|
||||
|
||||
1. Ensure ventilation calculations are performed.
|
||||
1. Building heat gain / loss calculation (Manual-J / Manual-N)
|
||||
1. Room x room for new construction or duct modifications.
|
||||
1. Block load for existing (can use original if available).
|
||||
1. Proper equipment capacity selection (Manual-S / Manual-CS)
|
||||
1. Properly matched systems (AHRI or CEE-AHRI)
|
||||
|
||||
Let's break the above items down to a rough estimated time to complete each of the items.
|
||||
|
||||
| Item | Time (minutes) |
|
||||
| ----------------------------------- | -------------- |
|
||||
| Ventilation calculations | 15 |
|
||||
| Manual-J (data gathering) | 30 |
|
||||
| Manual-J (data entry / calculation) | 30 |
|
||||
| Manual-S | 15 |
|
||||
| AHRI | 15 |
|
||||
| **Total** | 105 |
|
||||
|
||||
> _The above items are obviously just estimations and the person's experience in the different areas / tools they use. Some of the items are
|
||||
> probably on the low side while others are probably on the high side._
|
||||
|
||||
This is 1.75 hours just to do the calculations required to meet the QI Standard. This does not include any of the time spent with the
|
||||
customer building value in you or your product recommendations.
|
||||
|
||||
When you want to not guess at some of the calculations then a blower door test is generally required in order to understand the leakage of
|
||||
the home, which adds even more time to the estimation process. Depending on the understanding you are looking for, the blower door test can
|
||||
add 30-180 minutes. This takes the total time to 2.25-4.75 hours.
|
||||
|
||||
## Pushing boxes
|
||||
|
||||
The majority of residential HVAC companies make the bulk of their income off of equipment sales, so they have to "feed the beast" by
|
||||
skipping steps in both the installation of equipment and the sales process in order to close jobs and keep the ship afloat.
|
||||
|
||||

|
||||
|
||||
This has helped contribute to these industry statistics:[^1]
|
||||
|
||||
- **Incorrect refrigerant charge in greater than 50-80% of systems.**
|
||||
- **Improper airflow:**
|
||||
- **70% above the rated 0.5" w.c.**
|
||||
- **47% above 0.7" w.c.**
|
||||
- **85% undersized / inappropriate filter.**
|
||||
- **70-80% of systems have at least one fault.**
|
||||
- **90-100% if duct leakage is considered.**
|
||||
|
||||
## Consumer responsibility
|
||||
|
||||
Let me be clear, I don't think that all the blame is on the industry here. The culture today is that everyone wants things for free and
|
||||
fast. They have been conditioned by online services and box stores. Should we not cater to those that aren't willing to do their leg work?
|
||||
Is it really our fault, if they don't care?
|
||||
|
||||
## Liability
|
||||
|
||||
While it's generally easy to shrug our shoulders and think that it's ok to just continue on because all the competitors are doing the same
|
||||
thing. There is at least the possibility that skipping steps can come back to bite you. If things ever went to litigation and the steps
|
||||
outlined in the QI Standard are ignored, then there is high odds you would loose.
|
||||
|
||||
No matter what you do to try and protect yourself (having customers sign-off, etc) does not adequately protect your company from litigation.
|
||||
There are stories out there where contractors were still held liable for not performing load calculations even though the consumer signed
|
||||
off on it, because it is not inline with "industry best practices."
|
||||
|
||||
# Summary
|
||||
|
||||
This has led me to the conclusion that free quotes are just bad for the industry in general. The path forward is a challenge (changing
|
||||
perception is hard). I don't know that I have answers on what the best path forward is, to be frank, but I do know that our current _status
|
||||
quo_ is subpar to say the least.
|
||||
|
||||
Unfortunately, I don't think the change is going to come from the industry, but that it's going to require the consumer base to be more
|
||||
educated and demand more from the industry. There have been many organizations that have dedicated years to changing the skill levels of
|
||||
technicians in the industry, they are very well needed / don't mistake my words here, however unless a company has faced litigation or
|
||||
facing requests on a regular basis that demand better results, then why would a company change!?!
|
||||
|
||||
I've been trying (unsuccessfully) to get rid of free quotes for 5+ years in my company. We try to educate customers during maintenance
|
||||
visits and when scheduling equipment estimates, however only about 10-20% choose to go down our paid Home Performance Assessment path. Our
|
||||
installation process does follow the QI Standard for the items that pertain to the setup / commissioning of the installed equipment, however
|
||||
there is just no sustainable way for us to completely follow the items outlined in this article without charging for our time, because at
|
||||
the end of the day we still have to be competitive in our market.
|
||||
|
||||
There are days that I can justify our actions to myself and also days that I just want to throw in the towel / not sacrifice our integrity.
|
||||
Integrity is something that I take very seriously, after all our companies tag line is _"Since 1954, Integrity is in the Housh!"_
|
||||
|
||||
As mentioned, I'm not sure what the best path forward is! I hate to not have answers, but some problems are just complex and somewhat beyond
|
||||
our control.
|
||||
|
||||
Let me know what you think some good solutions are.
|
||||
|
||||
- Does your company follow the QI Standard?
|
||||
- What are resources that you've found helpful in educating your customers?
|
||||
|
||||
[^1]: DOE (2018)
|
||||
@@ -7,8 +7,8 @@ summary: Build an example application using Vapor and HTMX.
|
||||
|
||||
## Introduction
|
||||
|
||||
This post is a quick example of creating a very basic todo web application using `Vapor` a swift web
|
||||
framework and `Htmx`, with no custom javascript required.
|
||||
This post is a quick example of creating a very basic todo web application using `Vapor` a swift web framework and `Htmx`, with no custom
|
||||
javascript required.
|
||||
|
||||
[Vapor](https://docs.vapor.codes)
|
||||
|
||||
@@ -30,9 +30,8 @@ Next, generate the project using the vapor command-line tool.
|
||||
vapor new todo-htmx --fluent.db sqlite --leaf
|
||||
```
|
||||
|
||||
The above command will generate a new project that uses an `SQLite` database along with vapor's
|
||||
`Leaf` templating engine. You can move into the project directory and browse around the files that
|
||||
are generated.
|
||||
The above command will generate a new project that uses an `SQLite` database along with vapor's `Leaf` templating engine. You can move into
|
||||
the project directory and browse around the files that are generated.
|
||||
|
||||
```bash
|
||||
cd todo-htmx
|
||||
@@ -40,8 +39,8 @@ cd todo-htmx
|
||||
|
||||
## Update the Controller
|
||||
|
||||
Open the `Sources/App/Controllers/TodoController.swift` file. This file handles the api routes for
|
||||
our `Todo` database model. Personally I like to prefix these routes with `api`.
|
||||
Open the `Sources/App/Controllers/TodoController.swift` file. This file handles the api routes for our `Todo` database model. Personally I
|
||||
like to prefix these routes with `api`.
|
||||
|
||||
Update the first line in the `boot(routes: RoutesBuilder)` function to look like this.
|
||||
|
||||
@@ -49,14 +48,13 @@ Update the first line in the `boot(routes: RoutesBuilder)` function to look like
|
||||
let todos = routes.grouped("api", "todos")
|
||||
```
|
||||
|
||||
Everything else can stay the same. This changes these routes to be exposed at
|
||||
`http://localhost:8080/api/todos`, which will allow our routes that return html views to be able to
|
||||
be exposed at `http://localhost:8080/todos`.
|
||||
Everything else can stay the same. This changes these routes to be exposed at `http://localhost:8080/api/todos`, which will allow our routes
|
||||
that return html views to be able to be exposed at `http://localhost:8080/todos`.
|
||||
|
||||
## Update the Todo Model
|
||||
|
||||
A todo is not very valuable without a way to tell if it needs to be completed or not. So, let's add
|
||||
a field to our database model (`Sources/App/Models/Todo.swift`).
|
||||
A todo is not very valuable without a way to tell if it needs to be completed or not. So, let's add a field to our database model
|
||||
(`Sources/App/Models/Todo.swift`).
|
||||
|
||||
Update the file to include the following:
|
||||
|
||||
@@ -97,8 +95,7 @@ final class Todo: Model, @unchecked Sendable {
|
||||
}
|
||||
```
|
||||
|
||||
Since we added a field to our database model, we also need to update the migration file
|
||||
(`Sources/App/Migrations/CreateTodo.swift`).
|
||||
Since we added a field to our database model, we also need to update the migration file (`Sources/App/Migrations/CreateTodo.swift`).
|
||||
|
||||
```swift
|
||||
import Fluent
|
||||
@@ -118,13 +115,12 @@ struct CreateTodo: AsyncMigration {
|
||||
}
|
||||
```
|
||||
|
||||
This just adds our new field to the database schema when we run the migrations, which we will do
|
||||
later on in the tutorial.
|
||||
This just adds our new field to the database schema when we run the migrations, which we will do later on in the tutorial.
|
||||
|
||||
### Update the Data Transfer Object
|
||||
|
||||
We also need to add the `complete` field to our data transfer object (`DTO`). This model is used as
|
||||
an intermediate between our database and the user.
|
||||
We also need to add the `complete` field to our data transfer object (`DTO`). This model is used as an intermediate between our database and
|
||||
the user.
|
||||
|
||||
```swift
|
||||
import Fluent
|
||||
@@ -150,11 +146,9 @@ struct TodoDTO: Content {
|
||||
|
||||
## Generate the View Templates
|
||||
|
||||
Our index template was already generated at `Resources/Views/index.leaf`, open the file and edit the
|
||||
contents to match the following.
|
||||
Our index template was already generated at `Resources/Views/index.leaf`, open the file and edit the contents to match the following.
|
||||
|
||||
> Note: You can learn more about the
|
||||
> [leaf templating engine here.](https://docs.vapor.codes/leaf/getting-started/)
|
||||
> Note: You can learn more about the [leaf templating engine here.](https://docs.vapor.codes/leaf/getting-started/)
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
@@ -182,18 +176,15 @@ contents to match the following.
|
||||
</html>
|
||||
```
|
||||
|
||||
The important parts here are the `<script>` tag in the head element which will include `Htmx` in our
|
||||
project.
|
||||
The important parts here are the `<script>` tag in the head element which will include `Htmx` in our project.
|
||||
|
||||
The head element also contains a link to a custom `css` stylesheet that we will create shortly.
|
||||
|
||||
We add a `form` element that will be used to generate a new todo item in the database. This is a
|
||||
basic / standard html form, but we are using `Htmx` to post the form contents to the route
|
||||
`POST http://localhost:8080/todos`, which we will create shortly.
|
||||
We add a `form` element that will be used to generate a new todo item in the database. This is a basic / standard html form, but we are
|
||||
using `Htmx` to post the form contents to the route `POST http://localhost:8080/todos`, which we will create shortly.
|
||||
|
||||
Then there's the `table` element that will contain the contents of our todos. When the page is
|
||||
loaded it will use `Htmx` to fetch the todos from `GET http://localhost:8080/todos` route, which we
|
||||
will create shortly.
|
||||
Then there's the `table` element that will contain the contents of our todos. When the page is loaded it will use `Htmx` to fetch the todos
|
||||
from `GET http://localhost:8080/todos` route, which we will create shortly.
|
||||
|
||||
### Todos Table Template
|
||||
|
||||
@@ -242,16 +233,14 @@ The contents of this file should be the following:
|
||||
</table>
|
||||
```
|
||||
|
||||
Here, we just create a table that is 3 columns wide from a list of todos that we will pass in to the
|
||||
template. We use `Htmx` to handle updating a todo if a user clicks a checkbox to mark the todo as
|
||||
`complete`, we also add a button in the last column of the table that we use `Htmx` to handle
|
||||
deleting a todo from the database.
|
||||
Here, we just create a table that is 3 columns wide from a list of todos that we will pass in to the template. We use `Htmx` to handle
|
||||
updating a todo if a user clicks a checkbox to mark the todo as `complete`, we also add a button in the last column of the table that we use
|
||||
`Htmx` to handle deleting a todo from the database.
|
||||
|
||||
## Controllers
|
||||
|
||||
The controllers handle the routes that our website exposes. The project template creates a
|
||||
controller for us that handles `JSON` / `API` requests, but we do need to make a couple of changes
|
||||
to the file (`Sources/App/Controllers/TodoController.swift`).
|
||||
The controllers handle the routes that our website exposes. The project template creates a controller for us that handles `JSON` / `API`
|
||||
requests, but we do need to make a couple of changes to the file (`Sources/App/Controllers/TodoController.swift`).
|
||||
|
||||
```swift
|
||||
import Fluent
|
||||
@@ -306,19 +295,16 @@ struct TodoController: RouteCollection {
|
||||
}
|
||||
```
|
||||
|
||||
The primary changes here are to add the `update(req: Request)` function at the bottom, which handles
|
||||
updating a todo that has already been created. This will be used when a user clicks on the checkbox
|
||||
to mark a todo as complete or incomplete.
|
||||
The primary changes here are to add the `update(req: Request)` function at the bottom, which handles updating a todo that has already been
|
||||
created. This will be used when a user clicks on the checkbox to mark a todo as complete or incomplete.
|
||||
|
||||
We also change the route in the `boot(routes: RoutesBuilder)` method to make all these routes
|
||||
accessible at `/api/todos` instead of the original `/todos` as we will use the `/todos` routes for
|
||||
returning our views from our view controller.
|
||||
We also change the route in the `boot(routes: RoutesBuilder)` method to make all these routes accessible at `/api/todos` instead of the
|
||||
original `/todos` as we will use the `/todos` routes for returning our views from our view controller.
|
||||
|
||||
### Todo View Controller
|
||||
|
||||
Next we need to create our view controller, it is what will be used to handle routes that should
|
||||
return `html` content for our website. This controller will actually use the api controller to do
|
||||
the majority of it's work.
|
||||
Next we need to create our view controller, it is what will be used to handle routes that should return `html` content for our website. This
|
||||
controller will actually use the api controller to do the majority of it's work.
|
||||
|
||||
The easiest thing is to make a copy of the current api controller:
|
||||
|
||||
@@ -373,9 +359,8 @@ struct TodoViewController: RouteCollection {
|
||||
}
|
||||
```
|
||||
|
||||
Here we use the api controller to do the heavy lifting of communicating with the database, then we
|
||||
just always return / render the `todos.leaf` template that we created earlier, which will update our
|
||||
web page with the list of todos retreived from the database.
|
||||
Here we use the api controller to do the heavy lifting of communicating with the database, then we just always return / render the
|
||||
`todos.leaf` template that we created earlier, which will update our web page with the list of todos retreived from the database.
|
||||
|
||||
> Note: There are better ways to handle this, however this is just a simple example.
|
||||
|
||||
@@ -401,8 +386,8 @@ func routes(_ app: Application) throws {
|
||||
}
|
||||
```
|
||||
|
||||
Here, we just add the `TodoViewController` at the bottom so vapor will be able to handle those
|
||||
routes and also update the title to be `Todos` (in the first `app.get` near the top).
|
||||
Here, we just add the `TodoViewController` at the bottom so vapor will be able to handle those routes and also update the title to be
|
||||
`Todos` (in the first `app.get` near the top).
|
||||
|
||||
## Build and Run
|
||||
|
||||
@@ -414,8 +399,8 @@ First, let's make sure the project builds.
|
||||
swift build
|
||||
```
|
||||
|
||||
This may take a minute if it's the first time building the project as it has to fetch the
|
||||
dependencies. If you experience problems here then make sure you don't have typos in your files.
|
||||
This may take a minute if it's the first time building the project as it has to fetch the dependencies. If you experience problems here then
|
||||
make sure you don't have typos in your files.
|
||||
|
||||
Next, we need to run the database migrations.
|
||||
|
||||
@@ -429,15 +414,15 @@ Finally, we can run the application.
|
||||
swift run App
|
||||
```
|
||||
|
||||
You should be able to open your browser and type in the url: `http://localhost:8080` to view the
|
||||
application. You can experiment with adding a new todo using the form.
|
||||
You should be able to open your browser and type in the url: `http://localhost:8080` to view the application. You can experiment with adding
|
||||
a new todo using the form.
|
||||
|
||||
> Note: To stop the application use `Ctrl-c`
|
||||
|
||||
## Bonus Styles
|
||||
|
||||
Hopefully you weren't blinded the first time you opened the application. You can add custom styles
|
||||
by creating a `css` file (`Public/css/main.css`).
|
||||
Hopefully you weren't blinded the first time you opened the application. You can add custom styles by creating a `css` file
|
||||
(`Public/css/main.css`).
|
||||
|
||||
```bash
|
||||
mkdir Public/css
|
||||
@@ -476,8 +461,8 @@ td {
|
||||
}
|
||||
```
|
||||
|
||||
Currently vapor does not know to serve files from the `Public` directory, so we need to update the
|
||||
`Sources/App/configure.swift` file, by uncommenting the line near the top.
|
||||
Currently vapor does not know to serve files from the `Public` directory, so we need to update the `Sources/App/configure.swift` file, by
|
||||
uncommenting the line near the top.
|
||||
|
||||
```swift
|
||||
import Fluent
|
||||
|
||||
BIN
content/articles/images/2023-08-10-coil-bypass-overview.png
LFS
Normal file
BIN
content/articles/images/2023-08-10-coil-bypass-overview.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-08-10-register-throw.png
LFS
Normal file
BIN
content/articles/images/2023-08-10-register-throw.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-08-10-rss-feed.gif
LFS
Normal file
BIN
content/articles/images/2023-08-10-rss-feed.gif
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-08-10-volume-equation.png
LFS
Normal file
BIN
content/articles/images/2023-08-10-volume-equation.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-08-formula.png
LFS
Normal file
BIN
content/articles/images/2023-09-08-formula.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-08-pounds-of-water-removed.png
LFS
Normal file
BIN
content/articles/images/2023-09-08-pounds-of-water-removed.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-08-solution.png
LFS
Normal file
BIN
content/articles/images/2023-09-08-solution.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-14-why-mini-splits-stink.png
LFS
Normal file
BIN
content/articles/images/2023-09-14-why-mini-splits-stink.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-15-pints-per-day-example.png
LFS
Normal file
BIN
content/articles/images/2023-09-15-pints-per-day-example.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-15-pints-per-day-example2.png
LFS
Normal file
BIN
content/articles/images/2023-09-15-pints-per-day-example2.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-15-pints-per-day.png
LFS
Normal file
BIN
content/articles/images/2023-09-15-pints-per-day.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-15-sizing-dehumidifier-by-latent-load.png
LFS
Normal file
BIN
content/articles/images/2023-09-15-sizing-dehumidifier-by-latent-load.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-18-dh-size.png
LFS
Normal file
BIN
content/articles/images/2023-09-18-dh-size.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-18-help.png
LFS
Normal file
BIN
content/articles/images/2023-09-18-help.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-18-introducing-psychrometrics-cli.png
LFS
Normal file
BIN
content/articles/images/2023-09-18-introducing-psychrometrics-cli.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-18-pounds-removed.png
LFS
Normal file
BIN
content/articles/images/2023-09-18-pounds-removed.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-18-properties.png
LFS
Normal file
BIN
content/articles/images/2023-09-18-properties.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-21-introduction-to-programming-for-hvac-1.png
LFS
Normal file
BIN
content/articles/images/2023-09-21-introduction-to-programming-for-hvac-1.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-21-spotlight.png
LFS
Normal file
BIN
content/articles/images/2023-09-21-spotlight.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-21-terminal-line.png
LFS
Normal file
BIN
content/articles/images/2023-09-21-terminal-line.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-21-terminal.png
LFS
Normal file
BIN
content/articles/images/2023-09-21-terminal.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-22-brew-output.png
LFS
Normal file
BIN
content/articles/images/2023-09-22-brew-output.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-22-introduction-to-programming-for-hvac-2.png
LFS
Normal file
BIN
content/articles/images/2023-09-22-introduction-to-programming-for-hvac-2.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-24-hello-output.png
LFS
Normal file
BIN
content/articles/images/2023-09-24-hello-output.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-24-introduction-to-programming-for-hvac-3.png
LFS
Normal file
BIN
content/articles/images/2023-09-24-introduction-to-programming-for-hvac-3.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-24-text-settings.png
LFS
Normal file
BIN
content/articles/images/2023-09-24-text-settings.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-26-greet-output.png
LFS
Normal file
BIN
content/articles/images/2023-09-26-greet-output.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-26-introduction-to-programming-for-hvac-4.png
LFS
Normal file
BIN
content/articles/images/2023-09-26-introduction-to-programming-for-hvac-4.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-09-26-part4-banner-transparent.png
LFS
Normal file
BIN
content/articles/images/2023-09-26-part4-banner-transparent.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-10-04-free-quotes-are-bad-for-the-industry.png
LFS
Normal file
BIN
content/articles/images/2023-10-04-free-quotes-are-bad-for-the-industry.png
LFS
Normal file
Binary file not shown.
BIN
content/articles/images/2023-10-04-sinking-boat.png
LFS
Normal file
BIN
content/articles/images/2023-10-04-sinking-boat.png
LFS
Normal file
Binary file not shown.
Reference in New Issue
Block a user