feat: Ports all existing articles and images.

This commit is contained in:
2025-02-20 12:14:09 -05:00
parent e0fb6129ad
commit 67dc3540d6
151 changed files with 10413 additions and 1631 deletions

View 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
![volume-equation](/articles/images/2023-08-10-volume-equation.png)
| **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).
![register-throw](/articles/images/2023-08-10-register-throw.png)
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/)

View 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.
![rss gif](/articles/images/2023-08-10-rss-feed.gif)
That's it.

View 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).
![chart](/articles/images/2023-09-08-pounds-of-water-removed.png)
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.
![formula](/articles/images/2023-09-08-formula.png)
| **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.
![solution](/articles/images/2023-09-08-solution.png)
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!

View 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!

View File

@@ -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.
![pints-per-day-formula](/articles/images/2023-09-15-pints-per-day.png)
| 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.
![pints-per-day-formula-example](/articles/images/2023-09-15-pints-per-day-example.png)
Or if we just want to cover the latent capacity at 85% of the full latent load.
![pints-per-day-formula-example](/articles/images/2023-09-15-pints-per-day-example2.png)
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!

View 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
```
![properties-output](/articles/images/2023-09-18-properties.png)
### 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
```
![dh-size](/articles/images/2023-09-18-dh-size.png)
### 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
```
![pounds-removed](/articles/images/2023-09-18-pounds-removed.png)
### Help
You can use `--help` option to show help and the list of commands provided.
![help](/articles/images/2023-09-18-help.png)
If you have any questions then feel free to email or message me. I hope some of you may find this application useful.

View File

@@ -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.
![spotlight](/articles/images/2023-09-21-spotlight.png)
### 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.
![terminal](/articles/images/2023-09-21-terminal.png)
Below is an image / explanation of what the default status line includes.
![terminal-line](/articles/images/2023-09-21-terminal-line.png)
### 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.

View File

@@ -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)"
```
![brew-output](/articles/images/2023-09-22-brew-output.png)
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.

View File

@@ -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_.
![text-settings](/articles/images/2023-09-24-text-settings.png)
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.
![hello-output](/articles/images/2023-09-24-hello-output.png)
### 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.

View File

@@ -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
```
![greet-output](/articles/images/2023-09-26-greet-output.png)
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.
![banner-transparent](/articles/images/2023-09-26-part4-banner-transparent.png)
> **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.

View File

@@ -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.
![sinking-boat](/articles/images/2023-10-04-sinking-boat.png)
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)

View File

@@ -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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.