Harvestly

How the countdown works.

One test, one forecast and two published tables give each batch of maize a number of storage days. Here is every step, with the numbers.

Try it on your own sacksJump to the tables

01 A day in the engine

Every evening at 17:00, five steps.

  1. 1. Starting moisture

    It comes only from the farmer’s own test. Salt sticks: above 15%, and the countdown uses 18%. Salt flows: below about 15%, and it uses 14.5%, never as proof of 13.5%. A hygrometer reading is converted with the moisture table at the reading’s temperature. A meter reading is used as read. Untested grain gets a request to test, never a countdown.

  2. 2. Drift

    Grain in woven sacks, cribs and floors takes on the moisture of the air around it. Each day it closes 5% of the gap to the moisture it would settle at in that air. Hermetic bags do not change. Drying grain is held until the next test.

    Example. Kitale in a normal October, 18.3 °C and 63% humidity 5, settles maize near 14.1% 6. A sack at 18% moves to 17.81% after one day.

  3. 3. Storage life used

    Each day uses 1 divided by the storage days at that temperature and moisture 7. When the fractions add up to 1, the grain has lost about 0.5% of its dry weight, which the source puts at roughly one US grade level. The source counts from harvest; the engine counts from the first test.

    Example. At 17.81% and 18.3 °C the table gives about 48 days, so that day uses 2.1% of the batch’s storage life.

  4. 4. Countdown and level

    The engine runs the days forward over the 7-day forecast, then repeats the forecast’s average, and counts the days until the life is used up. HIGH: 80% used, or 14 days or fewer. MEDIUM: 50% used, or 30 days or fewer. These thresholds are ours, set for the lead time sun-drying needs in a wet season.

  5. 5. What is sent

    At most one unprompted message a day, in this order: rain in the next 24 hours while the farmer is drying; a changed recommendation; a worse countdown (risk up, or days left halved and 60 or fewer); a spaced and capped reminder; the one-off insect reminder. A reply is answered at once and never uses up the evening slot.

    The repeat rules

    An ordinary repeat is spaced at least 3 days apart and sent at most twice per test. Re-tests are asked at most twice in 30 days, and rain alerts pause after three go unanswered.

    Urgent warnings (HIGH) repeat weekly, at most four times per test result. The fourth says it is the last reminder on that result and asks for a new test; after it the engine stays quiet until a new test result restarts the count, so a batch can go silent while its countdown is at zero.

02 Drift

Sixty days in a sack.

The same rule, run forward. Wet grain in dry air dries slowly. Dry grain in damp air does not stay dry: at 85% humidity sack B heads for 18.6% and passes the 13.5% line within days. That is the failure Harvestly watches for.

12%14%16%18%Day 015304560AB
  • A. Starts at 18%, in dry air (18.3 °C, 63% humidity). Falls toward 14.1%.
  • B. Starts at 13%, in damp air (18 °C, 85% humidity). Rises toward 18.6%.
  • The 13.5% limit.

Engine rule: 5% of the gap closed each day, in woven sacks. The 5% rate is a calibration assumption, not a measurement.

03 The tables

The two published tables.

Both are US corn tables from the University of Arkansas Extension, copied into the engine and checked cell by cell. Shading: in the first table, amber from 13.5% upward; in the second, amber as the days run short. Between the printed values the engine interpolates. The tables are in degrees Fahrenheit; the rows show both.

Scroll the table sideways.

Equilibrium moisture of maize, % wet basis: where grain settles in air at a given temperature and humidity (Arkansas FSA1074, Table A 6)
Temperature (rows), humidity % (columns)2530354045505560657075808590
2 °C (35 °F)9.310.311.212.113.013.914.815.716.617.618.719.821.222.9
4 °C (40 °F)9.110.010.911.812.713.514.415.316.217.118.219.320.722.3
7 °C (45 °F)8.89.810.611.512.313.214.014.915.816.717.718.920.221.8
10 °C (50 °F)8.69.510.411.212.012.913.714.515.416.317.318.519.821.4
13 °C (55 °F)8.49.310.111.011.812.613.414.215.116.017.018.119.320.9
16 °C (60 °F)8.29.19.910.711.512.313.113.914.815.716.617.718.920.5
18 °C (65 °F)8.08.99.710.511.312.012.813.614.515.316.317.418.620.1
21 °C (70 °F)7.98.79.510.311.011.812.613.414.215.016.017.018.219.8
24 °C (75 °F)7.78.59.310.110.811.612.313.113.914.815.716.717.919.4
27 °C (80 °F)7.68.49.19.910.611.412.112.913.714.515.416.417.619.1
29 °C (85 °F)7.48.29.09.710.411.211.912.613.414.315.216.217.318.8
32 °C (90 °F)7.38.18.89.510.311.011.712.413.214.014.915.917.018.5
35 °C (95 °F)7.27.98.79.410.110.811.512.213.013.814.715.616.818.2
38 °C (100 °F)7.17.88.59.29.910.611.312.012.813.614.515.416.517.9

Scroll the table sideways.

Storage period for maize, days to about 0.5% dry-matter loss, by grain temperature and moisture (Arkansas FSA1058, Table 1 7)
Temperature (rows), moisture % (columns)15171921232530
2 °C (35 °F)2,1266712951611027241
4 °C (40 °F)1,413448197107684827
7 °C (45 °F)93129913172453218
10 °C (50 °F)6211998848302112
13 °C (55 °F)414133583221148
16 °C (60 °F)27588392214106
18 °C (65 °F)2066629161185
21 °C (70 °F)154492212864
24 °C (75 °F)11537169653

04 What the farmer is told

Eighteen messages, in two languages.

Plain characters only, two SMS at most. Fields in this style are filled in per batch. Draft wording.

Kiswahili is a draft, not yet reviewed by a native speaker.
Show all 18 messages
The engine’s message templates
SituationCodeMessage
Drying, and rain is dueRain in the next 24 hours: 60% chance or 5 mm.RAIN_COVERHarvestly: Rain likely rain when (rain). Cover your drying maize or bring it indoors now. Reply 1 when covered. credit date.Harvestly: Mvua inatarajiwa rain when (rain). Funika mahindi unayoanika au uyaingize ndani sasa. Jibu 1 ukishafunika. credit date.
Not yet testedAsks for a meter reading first and offers the salt test as a draft, with no amounts or times. At most 3 requests.TEST_FIRSTHarvestly: We do not know how wet your maize is yet. Test it before you store it: use a moisture meter at your co-op or NCPB depot and reply METER and the number, e.g. METER 14.2. Salt test (draft, unconfirmed): reply SALT YES if salt sticks, SALT NO if it stays loose.Harvestly: Hatujui bado mahindi yako yana unyevu kiasi gani. Yapime kabla ya kuhifadhi: tumia mita ya unyevu kwenye chama chako au bohari ya NCPB kisha jibu MITA na namba, mf. MITA 14.2. Kipimo cha chumvi (rasimu, bado hakijathibitishwa): jibu CHUMVI NDIYO chumvi ikinata, CHUMVI HAPANA ikibaki huru.
Sealed, but the test said wetOpen the bags and dry the maize.OPEN_AND_DRYHarvestly: Maize sealed at 14% moisture or more can still go mouldy (evidence). Storage time left: risk. Open the bags, dry the maize in full sun and reply DRYING. Reseal only after a test shows it is dry.Harvestly: Mahindi yaliyofungwa yakiwa na unyevu wa 14% au zaidi bado yanaweza kuota kuvu (evidence). Muda uliobaki: risk. Fungua mifuko, anika juani kisha jibu ANIKA. Usifunge tena mpaka kipimo kionyeshe yamekauka.
Sealed in hermetic bags on a salt test onlyAsks for a meter check within a week.CONFIRM_DRYHarvestly: Sealed bags protect maize only below 14% moisture, and this is not yet confirmed (evidence). Within a week, get a meter check at checkpoint and reply METER with the number.Harvestly: Mifuko isiyopitisha hewa hulinda mahindi yenye unyevu chini ya 14% tu, na hili bado halijathibitishwa (evidence). Ndani ya wiki moja, pima kwa mita katika checkpoint kisha tuma MITA na namba.
Most of the storage life used80% used.SORT_AND_SELLHarvestly: This batch has used most of its estimated storage time. Check it today: remove mouldy or discoloured grain (do not eat it or feed it to animals), then sell or use this batch first.Harvestly: Mahindi haya yametumia sehemu kubwa ya muda wa uhifadhi uliokadiriwa. Yakague leo: ondoa punje zenye kuvu au zilizobadilika rangi (usizile wala usiwalishe mifugo), kisha yauze au uyatumie kwanza.
HIGH risk, repeatedAn unanswered urgent warning, spaced and capped.HIGH_ALERTHarvestly: URGENT. Storage time left: risk. Check this maize today: remove mouldy or discoloured grain (do not eat it or feed it to animals), then sell or use it first. closingHarvestly: HARAKA. Muda uliobaki: risk. Kagua mahindi haya leo: ondoa punje zenye kuvu au zilizobadilika rangi (usizile wala usiwalishe mifugo), kisha yauze au uyatumie kwanza. closing
The test says wetSent again if the countdown halves or the risk level rises, and at most twice more while it stays HIGH.DRY_NOWHarvestly: Your maize is too wet to store (evidence). Storage time left: risk. Dry it on a tarpaulin in full sunreply drying, then test again. credit date.Harvestly: Mahindi yako yana unyevu mwingi mno kuhifadhiwa (evidence). Muda uliobaki: risk. Yaanike juu ya turubai juanireply drying, kisha pima tena. credit date.
The estimate has moved past the testA full point past the salt line, up or down.RETESTHarvestly: why (evidence). Storage time left: risk. Do the salt test today and reply SALT YES or SALT NO. credit date.Harvestly: why (evidence). Muda uliobaki: risk. Fanya kipimo cha chumvi leo kisha jibu CHUMVI NDIYO au CHUMVI HAPANA. credit date.
Salt test passed, or a reading of 13.6–15%Answers a test. Never pushed on an estimate.NEARLY_DRYHarvestly: Not yet proven dry enough to seal or sell (evidence); the limit is 13.5%. Dry more in full sun if needed, then confirm with a meter at checkpoint. Reply METER and the number.Harvestly: Bado haijathibitishwa kuwa mahindi yamekauka vya kutosha kufungwa au kuuzwa (evidence); kiwango ni 13.5%. Anika zaidi juani ikihitajika, kisha thibitisha kwa mita katika checkpoint. Jibu MITA na namba.
Meter or hygrometer at 13.5% or belowThe only message that says grain is dry.READY_TO_STOREHarvestly: Dry enough to store (evidence). Seal it in hermetic bags (stockist) or deposit it at warehouse for a warehouse receipt. Reply SEALED, SOLD or DEPOSITED when done.Harvestly: Mahindi yamekauka vya kutosha (evidence). Yafunge kwenye mifuko isiyopitisha hewa (stockist) au yaweke kwenye warehouse upate stakabadhi ya ghala. Ukimaliza jibu NIMEFUNGA, NIMEUZA au GHALANI.
Seven weeks or more in sacks, measured dryOne reminder that insects get more likely the longer grain stays in sacks, with a pointer to hermetic bags.INSECT_REMINDERHarvestly: Your maize has been in sacks or open storage for number weeks. Weevil damage grows the longer maize stays in sacks. It tested dry, so consider moving it into hermetic bags (stockist) or selling soon.Harvestly: Mahindi yako yamekaa kwenye magunia au hifadhi ya wazi wiki number. Uharibifu wa fukusi huongezeka mahindi yakikaa muda mrefu kwenye magunia. Kipimo kilionyesha yamekauka, kwa hiyo fikiria kuyahamishia kwenye mifuko isiyopitisha hewa (stockist) au kuyauza mapema.
A reading or a storage change is recordedGives the last reading and when it was taken, then the estimate since, labelled as an estimate.STATUSHarvestly: Recorded (measured). Storage time left: risk. This is an estimate, not a guarantee.Harvestly: Tumepokea (measured). Muda wa kuhifadhi uliobaki: risk. Ni makadirio, si hakikisho.
At registrationSays what the messages are, credits the weather source, and explains STOP.WELCOMEHarvestly: Welcome. These messages give storage advice for your maize by SMS. It is an estimate. Weather data by Open-Meteo.com (CC BY 4.0). Reply STOP at any time to stop all messages.Harvestly: Karibu. Ujumbe huu unatoa ushauri wa kuhifadhi mahindi yako kwa SMS. Ni makadirio. Data ya hali ya hewa: Open-Meteo.com (CC BY 4.0). Jibu SIMAMISHA wakati wowote kusimamisha ujumbe wote.
A reply it does not understandLists the replies it knows.HELPHarvestly: Sorry, we did not understand. Reply SALT YES, SALT NO, METER 14.2, HYGRO 62 18, DRYING, SACKS, SEALED, SOLD, DEPOSITED or STOP.Harvestly: Samahani, hatukuelewa. Jibu CHUMVI NDIYO, CHUMVI HAPANA, MITA 14.2, HYGRO 62 18, ANIKA, MAGUNIA, NIMEFUNGA, NIMEUZA, GHALANI au SIMAMISHA.
An acknowledgementTHANKSHarvestly: Thank you, noted.Harvestly: Asante, tumepokea.
Other messageSTART_OKHarvestly: Messages are on again for this number. To register grain reply JOIN <ward> <storage> <bags>, e.g. JOIN KITALE SACK 12. Reply STOP to stop.Harvestly: Ujumbe umewashwa tena kwa namba hii. Kusajili mahindi jibu SAJILI <kata> <hifadhi> <magunia>, mf. SAJILI KITALE MAGUNIA 12. Jibu SIMAMISHA kusimamisha.
The batch is sold or depositedAlerts for the batch end.CLOSEDHarvestly: Noted. Alerts for this batch have ended. Reply START to restart them.Harvestly: Tumepokea. Arifa za mahindi haya zimekoma. Jibu ANZA kuziwasha tena.
The farmer replies STOPNo more messages until START.STOPPEDHarvestly: You will get no more messages on this number, for any batch. Reply START to restart.Harvestly: Hutapokea ujumbe zaidi kwenye namba hii, kwa mahindi yoyote. Jibu ANZA kuanza tena.

05 The parameters

Fifteen parameters, each labelled.

Labels: SOURCE from a publication, SOURCE-BASED our reading of one, CALIBRATION our assumption, PROGRAMME a rule we chose, UNVALIDATED not checked against its source or against Kenyan data.

The 15 parameters with their names in the code
ParameterValueLabelWhere it comes fromIn the code
1Moisture table14 × 14 values: 35–100 °F, 25–90% humiditySOURCEUniversity of Arkansas Extension FSA1074, Table A 6. Checked cell by cell against the publication.EMC_TABLE
2Storage time table9 × 7 values: 35–75 °F, 15–30% moistureSOURCEUniversity of Arkansas Extension FSA1058, Table 1 7. Checked cell by cell. Time to about 0.5% dry-matter loss, a US grade level. The source counts from harvest; the engine counts from the first test.AST_TABLE
3Limit for storage, sale and warehouse intake13.5% moistureSOURCEEast African Standard EAS 2, draft revision DEAS 2:2024 3. This is the limit for sale; Arkansas guidance for keeping corn a full year is 12%.EAS_MAX_MC
4Limit for hermetic bags14% moistureSOURCENg’ang’a et al. 2016a 4, cited and not re-opened in our checks: sealed bags stop aflatoxin building up only below 14%.HERMETIC_MAX_MC
5Salt test line15% moistureUNVALIDATEDSecondary, unverified: a rule of thumb attributed to Johnson 1992 18. We have not opened that paper, so the 15% line is not checked against it. The salt-test protocol is being verified, so our first message gives no amounts or times. Only a meter, hygrometer or depot reading clears grain. The protocol asks for non-iodised salt.SALT_LINE_MC
6Week-7 weevil reminder49 days in sacksSOURCE-BASEDBased on Ng’ang’a et al. 2016b 22, one trial in Makueni. The week-7 timing is our reading and is not stated in the abstract. The count starts at the first test, not at harvest.INSECT_REMINDER_DAYS
7Moisture used when salt sticks18%CALIBRATIONOur assumption. The true value is only known to be above 15%. A pilot would replace it with meter readings.SALT_STICKY_MC
8Moisture used when salt flows14.5%CALIBRATIONOur assumption: at most about 15%. Never treated as proof of 13.5%.SALT_FLOWS_MC
9Drift in sacks, cribs and floors5% of the gap to the air’s equilibrium moisture, each dayCALIBRATIONOur assumption, not fitted to data. Afzal et al. 21 report grain wetting from 12.5% to 15.6% over 2 months in polypropylene bags in Pakistan (final reading only), the same order of magnitude.SACK_EXCHANGE_RATE
10Grain temperatureThe day’s mean air temperatureCALIBRATIONA stand-in. Grain temperature is not air temperature.temp_c
11Risk levelsHIGH: 80% of storage life used, or 14 days or fewer. MEDIUM: 50%, or 30 days or fewer. Warn again when the countdown has halved and is 60 days or fewer.PROGRAMMEOur thresholds, set for the lead time sun-drying needs in a wet season.HIGH_LIFE, HIGH_DAYS, MEDIUM_LIFE, MEDIUM_DAYS, WORSE_FACTOR
12Rain alert60% chance, or 5 mm, in the next 24 hours, while grain is dryingPROGRAMMEOur rule.RAIN_PROB_ALERT, RAIN_MM_ALERT
13Spacing and cap of repeatsOne rule for an unanswered HIGH batch: after the ordinary advice message (repeated at most twice, 3 days apart, sealed bags 7), an urgent reminder goes out weekly, at most four times per test result. The fourth says it is the last reminder, then nothing more is sent until a new test resultPROGRAMMEOur rule, against alert fatigue.REMIND_GAP_DAYS, SEALED_GAP_DAYS, REPEAT_MAX, HIGH_ALERT_GAP_DAYS, HIGH_ALERT_MAX
14Re-test triggerThe estimate is 1 point past the salt line (16% going up, 14% going down). At most 2 re-test requests in 30 daysPROGRAMMEOur rule. The engine never orders drying on an estimate alone.RETEST_MARGIN, RETEST_PER_30_DAYS
15Other capsAn untested farmer is asked to test at most 3 times. Rain alerts pause after 3 unanswered. One proactive message a dayPROGRAMMEOur rule.TEST_REMINDERS_MAX, RAIN_UNACKED_MAX
Also in the code
  • HORIZON_DAYS = 365. A countdown is capped at 365 days. The site shows 365+.
  • MAX_AST_DAYS = 3650. Storage time is capped at 3,650 days.
  • Forecast beyond day 7. After the 7-day forecast the engine repeats the forecast’s average.
  • Humidity clamp. Humidity above 90% is treated as 90%, and below 25% as 25%, because the moisture table ends there.
  • Same drift for all permeable storage. Sacks, cribs and floors drift at the same rate.
  • PLACE_MAX_CHARS. A place or stockist name is cut to a fixed length so a message stays within two SMS.
What the demos assume
  • CALIBRATION Salt that sticks is treated as 18% moisture (the true value is anything above 15%).
  • CALIBRATION Salt that flows is treated as 14.5% and never counts as proof of 13.5% or less.
  • CALIBRATION A woven sack closes 5% of the gap to the air's equilibrium moisture per day. The headline demo (261 days, then 34) depends on it: with 0%/day it reads 45, 43, 42 days; with 2%/day 145, 143, 38.
  • CALIBRATION Grain temperature equals the daily mean air temperature (the storage-time table is for grain temperature).
  • PROGRAMME Alert thresholds (80% / 50% of life, 14 / 30 days), spacing and caps are design rules, not findings.
  • UNVALIDATED The Arkansas tables were built for US corn and have not been validated for Kenyan white maize.
  • UNVALIDATED Outdoor regional weather stands in for the conditions inside the sack.
  • UNVALIDATED Daily means of temperature and humidity are used although the moisture table is not linear.
  • UNVALIDATED The storage-life clock starts at the farmer's first test, not at harvest (the source clocks from harvest).
  • UNVALIDATED Drying grain keeps its tested moisture and still uses up storage life at that moisture.
  • UNVALIDATED Hermetic bags are perfectly sealed: moisture stays constant.
  • UNVALIDATED Weather beyond the 7-day forecast equals the 7-day mean.
  • PROGRAMME A countdown is capped at 365 days (HORIZON_DAYS) and storage time at 3650 days (MAX_AST_DAYS); a 365 means 365 or more.
  • UNVALIDATED Sacks, cribs and floors all drift at the same rate.
  • UNVALIDATED Relative humidity above 90% is treated as 90% (the table ends there), and below 25% as 25%.

06 How it is checked

How it is checked.

The Python reference has automated tests. Its results are published as vectors.json: moisture values, storage-time values and day-by-day scenarios that any other version must reproduce. The JavaScript behind the calculator and the week replay on this site is checked against them by tools/test-engine-js.mjs, and a script asserts the replay equals vectors.json before the data is written.

What is not validated, and the pilot status, are listed once on the home page.